c# - yyyy - datetime sql




كيف يمكنني حساب عمر شخص ما في C#؟ (20)

إصدار SQL:

declare @dd smalldatetime = '1980-04-01'
declare @age int = YEAR(GETDATE())-YEAR(@dd)
if (@dd> DATEADD(YYYY, -@age, GETDATE())) set @age = @age -1

print @age  

بالنظر إلى تاريخ DateTime يمثل عيد ميلاد شخص ما ، كيف أحسب عمره بالسنوات؟


إن أبسط طريقة وجدتها على الإطلاق هي هذه. كان يعمل بشكل صحيح للولايات المتحدة وأوروبا الغربية لغات. لا يمكن التحدث إلى لغات أخرى ، خاصة أماكن مثل الصين. 4 يقارن إضافية ، على الأكثر ، بعد حساب الأولي للعمر.

public int AgeInYears(DateTime birthDate, DateTime referenceDate)
{
  Debug.Assert(referenceDate >= birthDate, 
               "birth date must be on or prior to the reference date");

  DateTime birth = birthDate.Date;
  DateTime reference = referenceDate.Date;
  int years = (reference.Year - birth.Year);

  //
  // an offset of -1 is applied if the birth date has 
  // not yet occurred in the current year.
  //
  if (reference.Month > birth.Month);
  else if (reference.Month < birth.Month) 
    --years;
  else // in birth month
  {
    if (reference.Day < birth.Day)
      --years;
  }

  return years ;
}

كنت أبحث عن الإجابات على هذا ولاحظت أن أحداً لم يشر إلى الآثار التنظيمية / القانونية للولادات التي تحدث في يوم قفزة. على سبيل المثال ، لكل ويكيبيديا ، إذا وُلدت في 29 فبراير في ولايات قضائية مختلفة ، يختلف عيد ميلادك الذي لا يقفز إلى قفزة:

  • في المملكة المتحدة وهونج كونج: إنه اليوم الترتيبي لهذا العام ، لذلك في اليوم التالي ، الأول من مارس هو عيد ميلادك.
  • في نيوزيلندا: إنه اليوم السابق ، 28 فبراير لأغراض ترخيص السائقين ، و 1 مارس لأغراض أخرى.
  • تايوان: إنه يوم 28 فبراير.

وأقرب ما يمكن أن أقوله ، في الولايات المتحدة ، فإن القوانين صامتة بشأن هذه المسألة ، الأمر الذي يترك الأمر للقانون العام وكيف تحدد الهيئات التنظيمية المختلفة الأشياء في لوائحها.

تحقيقًا لهذه الغاية ، هناك تحسن:

public enum LeapDayRule
{
  OrdinalDay     = 1 ,
  LastDayOfMonth = 2 ,
}

static int ComputeAgeInYears(DateTime birth, DateTime reference, LeapYearBirthdayRule ruleInEffect)
{
  bool isLeapYearBirthday = CultureInfo.CurrentCulture.Calendar.IsLeapDay(birth.Year, birth.Month, birth.Day);
  DateTime cutoff;

  if (isLeapYearBirthday && !DateTime.IsLeapYear(reference.Year))
  {
    switch (ruleInEffect)
    {
      case LeapDayRule.OrdinalDay:
        cutoff = new DateTime(reference.Year, 1, 1)
                             .AddDays(birth.DayOfYear - 1);
        break;

      case LeapDayRule.LastDayOfMonth:
        cutoff = new DateTime(reference.Year, birth.Month, 1)
                             .AddMonths(1)
                             .AddDays(-1);
        break;

      default:
        throw new InvalidOperationException();
    }
  }
  else
  {
    cutoff = new DateTime(reference.Year, birth.Month, birth.Day);
  }

  int age = (reference.Year - birth.Year) + (reference >= cutoff ? 0 : -1);
  return age < 0 ? 0 : age;
}

تجدر الإشارة إلى أن هذا الرمز يفترض:

  • الغربية (الأوروبية) حساب العمر ، و
  • تقويم ، مثل التقويم الميلادي الذي يدرج يوم قفزة واحد في نهاية الشهر.

لدي طريقة مخصصة لحساب العمر ، بالإضافة إلى رسالة التحقق من صحة المكافأة فقط في حالة ما إذا كان يساعد:

public void GetAge(DateTime dob, DateTime now, out int years, out int months, out int days)
{
    years = 0;
    months = 0;
    days = 0;

    DateTime tmpdob = new DateTime(dob.Year, dob.Month, 1);
    DateTime tmpnow = new DateTime(now.Year, now.Month, 1);

    while (tmpdob.AddYears(years).AddMonths(months) < tmpnow)
    {
        months++;
        if (months > 12)
        {
            years++;
            months = months - 12;
        }
    }

    if (now.Day >= dob.Day)
        days = days + now.Day - dob.Day;
    else
    {
        months--;
        if (months < 0)
        {
            years--;
            months = months + 12;
        }
        days += DateTime.DaysInMonth(now.AddMonths(-1).Year, now.AddMonths(-1).Month) + now.Day - dob.Day;
    }

    if (DateTime.IsLeapYear(dob.Year) && dob.Month == 2 && dob.Day == 29 && now >= new DateTime(now.Year, 3, 1))
        days++;

}   

private string ValidateDate(DateTime dob) //This method will validate the date
{
    int Years = 0; int Months = 0; int Days = 0;

    GetAge(dob, DateTime.Now, out Years, out Months, out Days);

    if (Years < 18)
        message =  Years + " is too young. Please try again on your 18th birthday.";
    else if (Years >= 65)
        message = Years + " is too old. Date of Birth must not be 65 or older.";
    else
        return null; //Denotes validation passed
}

طريقة الاتصال هنا وتمرير قيمة تاريخ (MM / dd / yyyy إذا تم تعيين الخادم إلى لغة الولايات المتحدة الأمريكية). استبدل هذا بأي شيء صندوق رسائل أو أي حاوية لعرضها:

DateTime dob = DateTime.Parse("03/10/1982");  

string message = ValidateDate(dob);

lbldatemessage.Visible = !StringIsNullOrWhitespace(message);
lbldatemessage.Text = message ?? ""; //Ternary if message is null then default to empty string

تذكر أنه يمكنك تنسيق الرسالة بالطريقة التي تريدها.


لقد استخدمت حل ScArcher2 لإجراء عملية حسابية دقيقة للسنة لعمر الأشخاص ، لكنني كنت بحاجة إلى المزيد من الوقت وحساب الأشهر والأيام مع السنوات.

    public static Dictionary<string,int> CurrentAgeInYearsMonthsDays(DateTime? ndtBirthDate, DateTime? ndtReferralDate)
    {
        //----------------------------------------------------------------------
        // Can't determine age if we don't have a dates.
        //----------------------------------------------------------------------
        if (ndtBirthDate == null) return null;
        if (ndtReferralDate == null) return null;

        DateTime dtBirthDate = Convert.ToDateTime(ndtBirthDate);
        DateTime dtReferralDate = Convert.ToDateTime(ndtReferralDate);

        //----------------------------------------------------------------------
        // Create our Variables
        //----------------------------------------------------------------------
        Dictionary<string, int> dYMD = new Dictionary<string,int>();
        int iNowDate, iBirthDate, iYears, iMonths, iDays;
        string sDif = "";

        //----------------------------------------------------------------------
        // Store off current date/time and DOB into local variables
        //---------------------------------------------------------------------- 
        iNowDate = int.Parse(dtReferralDate.ToString("yyyyMMdd"));
        iBirthDate = int.Parse(dtBirthDate.ToString("yyyyMMdd"));

        //----------------------------------------------------------------------
        // Calculate Years
        //----------------------------------------------------------------------
        sDif = (iNowDate - iBirthDate).ToString();
        iYears = int.Parse(sDif.Substring(0, sDif.Length - 4));

        //----------------------------------------------------------------------
        // Store Years in Return Value
        //----------------------------------------------------------------------
        dYMD.Add("Years", iYears);

        //----------------------------------------------------------------------
        // Calculate Months
        //----------------------------------------------------------------------
        if (dtBirthDate.Month > dtReferralDate.Month)
            iMonths = 12 - dtBirthDate.Month + dtReferralDate.Month - 1;
        else
            iMonths = dtBirthDate.Month - dtReferralDate.Month;

        //----------------------------------------------------------------------
        // Store Months in Return Value
        //----------------------------------------------------------------------
        dYMD.Add("Months", iMonths);

        //----------------------------------------------------------------------
        // Calculate Remaining Days
        //----------------------------------------------------------------------
        if (dtBirthDate.Day > dtReferralDate.Day)
            //Logic: Figure out the days in month previous to the current month, or the admitted month.
            //       Subtract the birthday from the total days which will give us how many days the person has lived since their birthdate day the previous month.
            //       then take the referral date and simply add the number of days the person has lived this month.

            //If referral date is january, we need to go back to the following year's December to get the days in that month.
            if (dtReferralDate.Month == 1)
                iDays = DateTime.DaysInMonth(dtReferralDate.Year - 1, 12) - dtBirthDate.Day + dtReferralDate.Day;       
            else
                iDays = DateTime.DaysInMonth(dtReferralDate.Year, dtReferralDate.Month - 1) - dtBirthDate.Day + dtReferralDate.Day;       
        else
            iDays = dtReferralDate.Day - dtBirthDate.Day;             

        //----------------------------------------------------------------------
        // Store Days in Return Value
        //----------------------------------------------------------------------
        dYMD.Add("Days", iDays);

        return dYMD;
}

هذا السؤال الكلاسيكي يستحق حل Noda Time .

static int GetAge(LocalDate dateOfBirth)
{
    Instant now = SystemClock.Instance.Now;

    // The target time zone is important.
    // It should align with the *current physical location* of the person
    // you are talking about.  When the whereabouts of that person are unknown,
    // then you use the time zone of the person who is *asking* for the age.
    // The time zone of birth is irrelevant!

    DateTimeZone zone = DateTimeZoneProviders.Tzdb["America/New_York"];

    LocalDate today = now.InZone(zone).Date;

    Period period = Period.Between(dateOfBirth, today, PeriodUnits.Years);

    return (int) period.Years;
}

الاستعمال:

LocalDate dateOfBirth = new LocalDate(1976, 8, 27);
int age = GetAge(dateOfBirth);

قد تكون مهتمًا أيضًا بالتحسينات التالية:

  • سيؤدي المرور على مدار الساعة كـ IClock ، بدلاً من SystemClock.Instance الاستخدام ، إلى تحسين إمكانية الاختبار.

  • من المحتمل أن تتغير المنطقة الزمنية المستهدفة ، لذلك تريد أيضًا DateTimeZone المعلمة.

راجع أيضًا منشور المدونة الخاص بي حول هذا الموضوع: التعامل مع أعياد الميلاد واحتفالات الذكرى السنوية الأخرى


هذه ليست إجابة مباشرة ، ولكن أكثر من التفكير الفلسفي حول المشكلة المطروحة من وجهة نظر شبه علمية.

أود أن أزعم أن السؤال لا يحدد الوحدة أو الثقافة التي يمكن من خلالها قياس العمر ، ويبدو أن معظم الإجابات تفترض وجود تمثيل سنوي صحيح. وحدة SI للوقت هي second ، يجب أن تكون إجابة الإجابة الصحيحة الصحيحة (بالطبع تفترض طبيعتها DateTime دون أي اعتبار على الإطلاق للآثار النسبية):

var lifeInSeconds = (DateTime.Now.Ticks - then.Ticks)/TickFactor;

في الطريقة المسيحية لحساب العمر بالسنوات:

var then = ... // Then, in this case the birthday
var now = DateTime.UtcNow;
int age = now.Year - then.Year;
if (now.AddYears(-age) < then) age--;

في التمويل ، هناك مشكلة مماثلة عند حساب شيء يشار إليه غالبًا باسم " عدد أيام الكسر" ، والذي يكون تقريبًا عددًا من السنوات لفترة معينة. والقضية العمر هي حقا مسألة قياس الوقت.

مثال للاتفاقية الفعلية / الفعلية (حساب جميع الأيام "بشكل صحيح"):

DateTime start, end = .... // Whatever, assume start is before end

double startYearContribution = 1 - (double) start.DayOfYear / (double) (DateTime.IsLeapYear(start.Year) ? 366 : 365);
double endYearContribution = (double)end.DayOfYear / (double)(DateTime.IsLeapYear(end.Year) ? 366 : 365);
double middleContribution = (double) (end.Year - start.Year - 1);

double DCF = startYearContribution + endYearContribution + middleContribution;

هناك طريقة شائعة جدًا لقياس الوقت عمومًا وهي "إجراء تسلسل" (يجب أن يكون المتأنق الذي أطلق اسم اتفاقية التاريخ على محمل الجد "):

DateTime start, end = .... // Whatever, assume start is before end
int days = (end - start).Days;

أتساءل كم من الوقت يتعين علينا الذهاب قبل أن يصبح العمر النسبي بالثواني أكثر فائدة من التقريب القاسي لدورات الدوران حول الشمس خلال فترة حياة المرء حتى الآن :) أو بعبارة أخرى ، عندما يجب إعطاء فترة ما موقعًا أو وظيفة تمثل الحركة لنفسها لتكون :)


هنا حل.

DateTime dateOfBirth = new DateTime(2000, 4, 18);
DateTime currentDate = DateTime.Now;

int ageInYears = 0;
int ageInMonths = 0;
int ageInDays = 0;

ageInDays = currentDate.Day - dateOfBirth.Day;
ageInMonths = currentDate.Month - dateOfBirth.Month;
ageInYears = currentDate.Year - dateOfBirth.Year;

if (ageInDays < 0)
{
    ageInDays += DateTime.DaysInMonth(currentDate.Year, currentDate.Month);
    ageInMonths = ageInMonths--;

    if (ageInMonths < 0)
    {
        ageInMonths += 12;
        ageInYears--;
    }
}

if (ageInMonths < 0)
{
    ageInMonths += 12;
    ageInYears--;
}

Console.WriteLine("{0}, {1}, {2}", ageInYears, ageInMonths, ageInDays);

2 المشاكل الرئيسية لحل هي:

1. احسب العمر الفعلي - بالسنوات والأشهر والأيام ، إلخ.

2. احسب العمر المتصور عمومًا - لا يهتم الأشخاص عادةً بالعمر الحقيقي ، ولكنهم يهتمون فقط بعيد ميلاده في العام الحالي.

حل 1 واضح:

DateTime birth = DateTime.Parse("1.1.2000");
DateTime today = DateTime.Today;     //we usually don't care about birth time
TimeSpan age = today - birth;        //.NET FCL should guarantee this as precise
double ageInDays = age.TotalDays;    //total number of days ... also precise
double daysInYear = 365.2425;        //statistical value for 400 years
double ageInYears = ageInDays / daysInYear;  //can be shifted ... not so precise

الحل لـ 2 هو الحل الذي ليس دقيقًا جدًا في تحديد العمر الإجمالي ، ولكن ينظر إليه على أنه دقيق. عادةً ما يستخدمه الناس ، عندما يحسبون عمرهم "يدويًا":

DateTime birth = DateTime.Parse("1.1.2000");
DateTime today = DateTime.Today;
int age = today.Year - birth.Year;    //people perceive their age in years

if (today.Month < birth.Month ||
   ((today.Month == birth.Month) && (today.Day < birth.Day)))
{
  age--;  //birthday in current year not yet reached, we are 1 year younger ;)
          //+ no birthday for 29.2. guys ... sorry, just wrong date for birth
}

ملاحظات إلى 2 .:

  • هذا هو الحل المفضل لدي
  • لا يمكننا استخدام DateTime.DayOfYear أو TimeSpans ، لأنها تحول عدد الأيام في السنوات الكبيسة
  • لقد وضعت هناك خطوط أكثر قليلا لسهولة القراءة

ملاحظة واحدة فقط ... أود أن أقوم بإنشاء طريقتين مثقلتين بشكل مفرط ، طريقة للاستخدام العام ، والثانية لملاءمة الاستخدام:

public static int GetAge(DateTime bithDay, DateTime today) 
{ 
  //chosen solution method body
}

public static int GetAge(DateTime birthDay) 
{ 
  return GetAge(birthDay, DateTime.Now);
}

إليك إجابة أخرى:

public static int AgeInYears(DateTime birthday, DateTime today)
{
    return ((today.Year - birthday.Year) * 372 + (today.Month - birthday.Month) * 31 + (today.Day - birthday.Day)) / 372;
}

لقد تم اختبار هذه الوحدة على نطاق واسع. يبدو قليلا "السحر". الرقم 372 هو عدد الأيام في السنة إذا كان كل شهر 31 يومًا.

تفسير لماذا يعمل ( رفعت من هنا ) هو:

لنقم بتعيين Yn = DateTime.Now.Year, Yb = birthday.Year, Mn = DateTime.Now.Month, Mb = birthday.Month, Dn = DateTime.Now.Day, Db = birthday.Day

age = Yn - Yb + (31*(Mn - Mb) + (Dn - Db)) / 372

نحن نعلم أن ما نحتاج إليه هو إما Yn-Yb إذا كان قد تم الوصول إلى التاريخ بالفعل ، Yn-Yb-1 إذا لم يحدث.

أ) إذا كانت Mn<Mb ، لدينا -341 <= 31*(Mn-Mb) <= -31 and -30 <= Dn-Db <= 30

-371 <= 31*(Mn - Mb) + (Dn - Db) <= -1

مع تقسيم صحيح

(31*(Mn - Mb) + (Dn - Db)) / 372 = -1

ب) إذا كان Mn=Mb و Dn<Db ، فلدينا 31*(Mn - Mb) = 0 and -30 <= Dn-Db <= -1

مع تقسيم صحيح ، مرة أخرى

(31*(Mn - Mb) + (Dn - Db)) / 372 = -1

c) إذا كان Mn>Mb ، فلدينا 31 <= 31*(Mn-Mb) <= 341 and -30 <= Dn-Db <= 30

1 <= 31*(Mn - Mb) + (Dn - Db) <= 371

مع تقسيم صحيح

(31*(Mn - Mb) + (Dn - Db)) / 372 = 0

د) إذا كان Mn=Mb و Dn>Db ، لدينا 31*(Mn - Mb) = 0 and 1 <= Dn-Db <= 3 0

مع تقسيم صحيح ، مرة أخرى

(31*(Mn - Mb) + (Dn - Db)) / 372 = 0

e) إذا كان Mn=Mb و Dn=Db ، فلدينا 31*(Mn - Mb) + Dn-Db = 0

وبالتالي (31*(Mn - Mb) + (Dn - Db)) / 372 = 0


ابقائها بسيطة (وربما غبية :)).

DateTime birth = new DateTime(1975, 09, 27, 01, 00, 00, 00);
TimeSpan ts = DateTime.Now - birth;
Console.WriteLine("You are approximately " + ts.TotalSeconds.ToString() + " seconds old.");

الإجابة البسيطة على ذلك هي تطبيق AddYears كما هو موضح أدناه لأن هذه هي الطريقة الأصلية الوحيدة لإضافة سنوات إلى 29 فبراير من سنوات AddYears والحصول على النتيجة الصحيحة من 28 فبراير لسنوات مشتركة.

يشعر البعض أن الأول من شهر مارس هو عيد الميلاد ، ولكن لا. ولا أي قاعدة رسمية تدعم هذا ، ولا يفسر المنطق المشترك لماذا يجب أن يكون لدى بعض المولودين في فبراير 75٪ من أعياد ميلادهم في شهر آخر.

علاوة على ذلك ، فإن أسلوب العمر يضيف نفسه DateTime إلى DateTime . من خلال ذلك يمكنك الحصول على العمر بأبسط طريقة ممكنة:

  1. قائمة الاغراض

int age = birthDate.Age ()؛

public static class DateTimeExtensions
{
    /// <summary>
    /// Calculates the age in years of the current System.DateTime object today.
    /// </summary>
    /// <param name="birthDate">The date of birth</param>
    /// <returns>Age in years today. 0 is returned for a future date of birth.</returns>
    public static int Age(this DateTime birthDate)
    {
        return Age(birthDate, DateTime.Today);
    }

    /// <summary>
    /// Calculates the age in years of the current System.DateTime object on a later date.
    /// </summary>
    /// <param name="birthDate">The date of birth</param>
    /// <param name="laterDate">The date on which to calculate the age.</param>
    /// <returns>Age in years on a later day. 0 is returned as minimum.</returns>
    public static int Age(this DateTime birthDate, DateTime laterDate)
    {
        int age;
        age = laterDate.Year - birthDate.Year;

        if (age > 0)
        {
            age -= Convert.ToInt32(laterDate.Date < birthDate.Date.AddYears(age));
        }
        else
        {
            age = 0;
        }

        return age;
    }
}

الآن ، قم بإجراء هذا الاختبار:

class Program
{
    static void Main(string[] args)
    {
        RunTest();
    }

    private static void RunTest()
    {
        DateTime birthDate = new DateTime(2000, 2, 28);
        DateTime laterDate = new DateTime(2011, 2, 27);
        string iso = "yyyy-MM-dd";

        for (int i = 0; i < 3; i++)
        {
            for (int j = 0; j < 3; j++)
            {
                Console.WriteLine("Birth date: " + birthDate.AddDays(i).ToString(iso) + "  Later date: " + laterDate.AddDays(j).ToString(iso) + "  Age: " + birthDate.AddDays(i).Age(laterDate.AddDays(j)).ToString());
            }
        }

        Console.ReadKey();
    }
}

مثال التاريخ الحرج هو هذا:

تاريخ الميلاد: 2000-02-29 تاريخ لاحق: 2011-02-28 العمر: 11

انتاج:

{
    Birth date: 2000-02-28  Later date: 2011-02-27  Age: 10
    Birth date: 2000-02-28  Later date: 2011-02-28  Age: 11
    Birth date: 2000-02-28  Later date: 2011-03-01  Age: 11
    Birth date: 2000-02-29  Later date: 2011-02-27  Age: 10
    Birth date: 2000-02-29  Later date: 2011-02-28  Age: 11
    Birth date: 2000-02-29  Later date: 2011-03-01  Age: 11
    Birth date: 2000-03-01  Later date: 2011-02-27  Age: 10
    Birth date: 2000-03-01  Later date: 2011-02-28  Age: 10
    Birth date: 2000-03-01  Later date: 2011-03-01  Age: 11
}

وللتاريخ الأحدث 2012-02-28:

{
    Birth date: 2000-02-28  Later date: 2012-02-28  Age: 12
    Birth date: 2000-02-28  Later date: 2012-02-29  Age: 12
    Birth date: 2000-02-28  Later date: 2012-03-01  Age: 12
    Birth date: 2000-02-29  Later date: 2012-02-28  Age: 11
    Birth date: 2000-02-29  Later date: 2012-02-29  Age: 12
    Birth date: 2000-02-29  Later date: 2012-03-01  Age: 12
    Birth date: 2000-03-01  Later date: 2012-02-28  Age: 11
    Birth date: 2000-03-01  Later date: 2012-02-29  Age: 11
    Birth date: 2000-03-01  Later date: 2012-03-01  Age: 12
}

انا استعمل هذا:

public static class DateTimeExtensions
{
    public static int Age(this DateTime birthDate)
    {
        return Age(birthDate, DateTime.Now);
    }

    public static int Age(this DateTime birthDate, DateTime offsetDate)
    {
        int result=0;
        result = offsetDate.Year - birthDate.Year;

        if (offsetDate.DayOfYear < birthDate.DayOfYear)
        {
              result--;
        }

        return result;
    }
}

لا أعرف كيف يمكن قبول الحل الخاطئ. تمت كتابة مقتطف C # الصحيح بواسطة Michael Stum

إليك مقتطف اختبار:

DateTime bDay = new DateTime(2000, 2, 29);
DateTime now = new DateTime(2009, 2, 28);
MessageBox.Show(string.Format("Test {0} {1} {2}",
                CalculateAgeWrong1(bDay, now),      // outputs 9
                CalculateAgeWrong2(bDay, now),      // outputs 9
                CalculateAgeCorrect(bDay, now),     // outputs 8
                CalculateAgeCorrect2(bDay, now)));  // outputs 8

هنا لديك الطرق:

public int CalculateAgeWrong1(DateTime birthDate, DateTime now)
{
    return new DateTime(now.Subtract(birthDate).Ticks).Year - 1;
}

public int CalculateAgeWrong2(DateTime birthDate, DateTime now)
{
    int age = now.Year - birthDate.Year;

    if (now < birthDate.AddYears(age))
        age--;

    return age;
}

public int CalculateAgeCorrect(DateTime birthDate, DateTime now)
{
    int age = now.Year - birthDate.Year;

    if (now.Month < birthDate.Month || (now.Month == birthDate.Month && now.Day < birthDate.Day))
        age--;

    return age;
}

public int CalculateAgeCorrect2(DateTime birthDate, DateTime now)
{
    int age = now.Year - birthDate.Year;

    // for leap years we need this
    if (birthDate > now.AddYears(-age)) age--;
    // don't use:
    // if (birthDate.AddYears(age) > now) age--;

    return age;
}

لقد تأخرت عن الحفلة ، لكن إليك بطانة واحدة:

int age = new DateTime(DateTime.Now.Subtract(birthday).Ticks).Year-1;

لقد قمت بإنشاء دالة محددة من قِبل مستخدم SQL Server لحساب عمر شخص ما ، بالنظر إلى تاريخ ميلاده. هذا مفيد عندما تحتاج إليه كجزء من استعلام:

using System;
using System.Data;
using System.Data.Sql;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;

public partial class UserDefinedFunctions
{
    [SqlFunction(DataAccess = DataAccessKind.Read)]
    public static SqlInt32 CalculateAge(string strBirthDate)
    {
        DateTime dtBirthDate = new DateTime();
        dtBirthDate = Convert.ToDateTime(strBirthDate);
        DateTime dtToday = DateTime.Now;

        // get the difference in years
        int years = dtToday.Year - dtBirthDate.Year;

        // subtract another year if we're before the
        // birth day in the current year
        if (dtToday.Month < dtBirthDate.Month || (dtToday.Month == dtBirthDate.Month && dtToday.Day < dtBirthDate.Day))
            years=years-1;

        int intCustomerAge = years;
        return intCustomerAge;
    }
};

هذا يعطي "مزيد من التفاصيل" لهذا السؤال. ربما هذا هو ما تبحث عنه

DateTime birth = new DateTime(1974, 8, 29);
DateTime today = DateTime.Now;
TimeSpan span = today - birth;
DateTime age = DateTime.MinValue + span;

// Make adjustment due to MinValue equalling 1/1/1
int years = age.Year - 1;
int months = age.Month - 1;
int days = age.Day - 1;

// Print out not only how many years old they are but give months and days as well
Console.Write("{0} years, {1} months, {2} days", years, months, days);

هذه هي النسخة التي نستخدمها هنا. إنه يعمل ، وهو بسيط إلى حد ما. إنها نفس فكرة جيف ، لكنني أعتقد أنها أكثر وضوحًا لأنها تفصل منطق طرح واحد ، لذلك فمن الأسهل فهمه.

public static int GetAge(this DateTime dateOfBirth, DateTime dateAsAt)
{
    return dateAsAt.Year - dateOfBirth.Year - (dateOfBirth.DayOfYear < dateAsAt.DayOfYear ? 0 : 1);
}

يمكنك توسيع عامل التشغيل الثلاثي لجعله أكثر وضوحًا ، إذا كنت تعتقد أن هذا النوع من الأشياء غير واضح.

من الواضح أن هذا يتم كطريقة للامتداد على DateTime ، ولكن من الواضح أنه يمكنك الاستيلاء على سطر واحد من التعليمات البرمجية التي تعمل وتضعها في أي مكان. نحن هنا لدينا التحميل الزائد لطريقة الامتداد التي تمر في DateTime.Now ، لمجرد اكتمالها.


هل نحن بحاجة إلى النظر في الأشخاص الذين تقل أعمارهم عن سنة واحدة؟ كثقافة صينية ، وصفنا عمر الأطفال الصغار بأنه شهرين أو 4 أسابيع.

فيما يلي تنفيذي ، ليس الأمر بسيطًا كما تصورت ، خاصةً التعامل مع التاريخ مثل 2/28.

public static string HowOld(DateTime birthday, DateTime now)
{
    if (now < birthday)
        throw new ArgumentOutOfRangeException("birthday must be less than now.");

    TimeSpan diff = now - birthday;
    int diffDays = (int)diff.TotalDays;

    if (diffDays > 7)//year, month and week
    {
        int age = now.Year - birthday.Year;

        if (birthday > now.AddYears(-age))
            age--;

        if (age > 0)
        {
            return age + (age > 1 ? " years" : " year");
        }
        else
        {// month and week
            DateTime d = birthday;
            int diffMonth = 1;

            while (d.AddMonths(diffMonth) <= now)
            {
                diffMonth++;
            }

            age = diffMonth-1;

            if (age == 1 && d.Day > now.Day)
                age--;

            if (age > 0)
            {
                return age + (age > 1 ? " months" : " month");
            }
            else
            {
                age = diffDays / 7;
                return age + (age > 1 ? " weeks" : " week");
            }
        }
    }
    else if (diffDays > 0)
    {
        int age = diffDays;
        return age + (age > 1 ? " days" : " day");
    }
    else
    {
        int age = diffDays;
        return "just born";
    }
}

لقد مر هذا التطبيق أدناه حالات الاختبار.

[TestMethod]
public void TestAge()
{
    string age = HowOld(new DateTime(2011, 1, 1), new DateTime(2012, 11, 30));
    Assert.AreEqual("1 year", age);

    age = HowOld(new DateTime(2011, 11, 30), new DateTime(2012, 11, 30));
    Assert.AreEqual("1 year", age);

    age = HowOld(new DateTime(2001, 1, 1), new DateTime(2012, 11, 30));
    Assert.AreEqual("11 years", age);

    age = HowOld(new DateTime(2012, 1, 1), new DateTime(2012, 11, 30));
    Assert.AreEqual("10 months", age);

    age = HowOld(new DateTime(2011, 12, 1), new DateTime(2012, 11, 30));
    Assert.AreEqual("11 months", age);

    age = HowOld(new DateTime(2012, 10, 1), new DateTime(2012, 11, 30));
    Assert.AreEqual("1 month", age);

    age = HowOld(new DateTime(2008, 2, 28), new DateTime(2009, 2, 28));
    Assert.AreEqual("1 year", age);

    age = HowOld(new DateTime(2008, 3, 28), new DateTime(2009, 2, 28));
    Assert.AreEqual("11 months", age);

    age = HowOld(new DateTime(2008, 3, 28), new DateTime(2009, 3, 28));
    Assert.AreEqual("1 year", age);

    age = HowOld(new DateTime(2009, 1, 28), new DateTime(2009, 2, 28));
    Assert.AreEqual("1 month", age);

    age = HowOld(new DateTime(2009, 2, 1), new DateTime(2009, 3, 1));
    Assert.AreEqual("1 month", age);

    // NOTE.
    // new DateTime(2008, 1, 31).AddMonths(1) == new DateTime(2009, 2, 28);
    // new DateTime(2008, 1, 28).AddMonths(1) == new DateTime(2009, 2, 28);
    age = HowOld(new DateTime(2009, 1, 31), new DateTime(2009, 2, 28));
    Assert.AreEqual("4 weeks", age);

    age = HowOld(new DateTime(2009, 2, 1), new DateTime(2009, 2, 28));
    Assert.AreEqual("3 weeks", age);

    age = HowOld(new DateTime(2009, 2, 1), new DateTime(2009, 3, 1));
    Assert.AreEqual("1 month", age);

    age = HowOld(new DateTime(2012, 11, 5), new DateTime(2012, 11, 30));
    Assert.AreEqual("3 weeks", age);

    age = HowOld(new DateTime(2012, 11, 1), new DateTime(2012, 11, 30));
    Assert.AreEqual("4 weeks", age);

    age = HowOld(new DateTime(2012, 11, 20), new DateTime(2012, 11, 30));
    Assert.AreEqual("1 week", age);

    age = HowOld(new DateTime(2012, 11, 25), new DateTime(2012, 11, 30));
    Assert.AreEqual("5 days", age);

    age = HowOld(new DateTime(2012, 11, 29), new DateTime(2012, 11, 30));
    Assert.AreEqual("1 day", age);

    age = HowOld(new DateTime(2012, 11, 30), new DateTime(2012, 11, 30));
    Assert.AreEqual("just born", age);

    age = HowOld(new DateTime(2000, 2, 29), new DateTime(2009, 2, 28));
    Assert.AreEqual("8 years", age);

    age = HowOld(new DateTime(2000, 2, 29), new DateTime(2009, 3, 1));
    Assert.AreEqual("9 years", age);

    Exception e = null;

    try
    {
        age = HowOld(new DateTime(2012, 12, 1), new DateTime(2012, 11, 30));
    }
    catch (ArgumentOutOfRangeException ex)
    {
        e = ex;
    }

    Assert.IsTrue(e != null);
}

آمل أن تكون مفيدة.


وظيفة أخرى ، ليس عن طريقي ولكن وجدت على شبكة الإنترنت وصقلها قليلاً:

public static int GetAge(DateTime birthDate)
{
    DateTime n = DateTime.Now; // To avoid a race condition around midnight
    int age = n.Year - birthDate.Year;

    if (n.Month < birthDate.Month || (n.Month == birthDate.Month && n.Day < birthDate.Day))
        age--;

    return age;
}

شيئان فقط يتبادران إلى ذهني: ماذا عن أشخاص من دول لا تستخدم التقويم الميلادي؟ DateTime.Now في الثقافة الخاصة بالخادم على ما أعتقد. لا أعرف مطلقًا أي معلومات عن العمل الفعلي مع التقاويم الآسيوية ولا أعرف ما إذا كانت هناك طريقة سهلة لتحويل التواريخ بين التقاويم ، ولكن في حال كنت تتساءل عن هؤلاء الرجال الصينيين منذ عام 4660 :-)


private int GetAge(int _year, int _month, int _day
{
    DateTime yourBirthDate= new DateTime(_year, _month, _day);

    DateTime todaysDateTime = DateTime.Today;
    int noOfYears = todaysDateTime.Year - yourBirthDate.Year;

    if (DateTime.Now.Month < yourBirthDate.Month ||
        (DateTime.Now.Month == yourBirthDate.Month && DateTime.Now.Day < yourBirthDate.Day))
    {
        noOfYears--;
    }

    return  noOfYears;
}






datetime