给定代表某人生日的DateTime,我如何计算他们的年龄(以年为单位)?


当前回答

我对DateTime一无所知,但我能做的就是:

using System;
                    
public class Program
{
    public static int getAge(int month, int day, int year) {
        DateTime today = DateTime.Today;
        int currentDay = today.Day;
        int currentYear = today.Year;
        int currentMonth = today.Month;
        int age = 0;
        if (currentMonth < month) {
            age -= 1;
        } else if (currentMonth == month) {
            if (currentDay < day) {
                age -= 1;
            }
        }
        currentYear -= year;
        age += currentYear;
        return age;
    }
    public static void Main()
    {
        int ageInYears = getAge(8, 10, 2007);
        Console.WriteLine(ageInYears);
    }
}

有点困惑,但仔细看代码,这一切都是有意义的。

其他回答

这里有一个小的C#代码示例,我总结了一下,请注意边缘情况,特别是闰年,并不是所有上述解决方案都考虑到这些情况。将答案推出来作为DateTime可能会导致问题,因为你可能会在一个特定的月份中投入太多的时间,例如2月的30天。

public string LoopAge(DateTime myDOB, DateTime FutureDate)
{
    int years = 0;
    int months = 0;
    int days = 0;

    DateTime tmpMyDOB = new DateTime(myDOB.Year, myDOB.Month, 1);

    DateTime tmpFutureDate = new DateTime(FutureDate.Year, FutureDate.Month, 1);

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

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

    }

    //add an extra day if the dob is a leap day
    if (DateTime.IsLeapYear(myDOB.Year) && myDOB.Month == 2 && myDOB.Day == 29)
    {
        //but only if the future date is less than 1st March
        if(FutureDate >= new DateTime(FutureDate.Year, 3,1))
            days++;
    }

    return "Years: " + years + " Months: " + months + " Days: " + days;
}

这个经典问题值得野田时间来解决。

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参数。

另请参阅我关于这个主题的博客文章:处理生日和其他周年纪念日

这是一个非常适合我的功能。没有计算,非常简单。

    public static string ToAge(this DateTime dob, DateTime? toDate = null)
    {
        if (!toDate.HasValue)
            toDate = DateTime.Now;
        var now = toDate.Value;

        if (now.CompareTo(dob) < 0)
            return "Future date";

        int years = now.Year - dob.Year;
        int months = now.Month - dob.Month;
        int days = now.Day - dob.Day;

        if (days < 0)
        {
            months--;
            days = DateTime.DaysInMonth(dob.Year, dob.Month) - dob.Day + now.Day;
        }

        if (months < 0)
        {
            years--;
            months = 12 + months;
        }


        return string.Format("{0} year(s), {1} month(s), {2} days(s)",
            years,
            months,
            days);
    }

这里是一个单元测试:

    [Test]
    public void ToAgeTests()
    {
        var date = new DateTime(2000, 1, 1);
        Assert.AreEqual("0 year(s), 0 month(s), 1 days(s)", new DateTime(1999, 12, 31).ToAge(date));
        Assert.AreEqual("0 year(s), 0 month(s), 0 days(s)", new DateTime(2000, 1, 1).ToAge(date));
        Assert.AreEqual("1 year(s), 0 month(s), 0 days(s)", new DateTime(1999, 1, 1).ToAge(date));
        Assert.AreEqual("0 year(s), 11 month(s), 0 days(s)", new DateTime(1999, 2, 1).ToAge(date));
        Assert.AreEqual("0 year(s), 10 month(s), 25 days(s)", new DateTime(1999, 2, 4).ToAge(date));
        Assert.AreEqual("0 year(s), 10 month(s), 1 days(s)", new DateTime(1999, 2, 28).ToAge(date));

        date = new DateTime(2000, 2, 15);
        Assert.AreEqual("0 year(s), 0 month(s), 28 days(s)", new DateTime(2000, 1, 18).ToAge(date));
    }

以下方法(从.NET类DateDiff的时间段库中提取)考虑区域性信息的日历:

// ----------------------------------------------------------------------
private static int YearDiff( DateTime date1, DateTime date2 )
{
  return YearDiff( date1, date2, DateTimeFormatInfo.CurrentInfo.Calendar );
} // YearDiff

// ----------------------------------------------------------------------
private static int YearDiff( DateTime date1, DateTime date2, Calendar calendar )
{
  if ( date1.Equals( date2 ) )
  {
    return 0;
  }

  int year1 = calendar.GetYear( date1 );
  int month1 = calendar.GetMonth( date1 );
  int year2 = calendar.GetYear( date2 );
  int month2 = calendar.GetMonth( date2 );

  // find the the day to compare
  int compareDay = date2.Day;
  int compareDaysPerMonth = calendar.GetDaysInMonth( year1, month1 );
  if ( compareDay > compareDaysPerMonth )
  {
    compareDay = compareDaysPerMonth;
  }

  // build the compare date
  DateTime compareDate = new DateTime( year1, month2, compareDay,
    date2.Hour, date2.Minute, date2.Second, date2.Millisecond );
  if ( date2 > date1 )
  {
    if ( compareDate < date1 )
    {
      compareDate = compareDate.AddYears( 1 );
    }
  }
  else
  {
    if ( compareDate > date1 )
    {
      compareDate = compareDate.AddYears( -1 );
    }
  }
  return year2 - calendar.GetYear( compareDate );
} // YearDiff

用法:

// ----------------------------------------------------------------------
public void CalculateAgeSamples()
{
  PrintAge( new DateTime( 2000, 02, 29 ), new DateTime( 2009, 02, 28 ) );
  // > Birthdate=29.02.2000, Age at 28.02.2009 is 8 years
  PrintAge( new DateTime( 2000, 02, 29 ), new DateTime( 2012, 02, 28 ) );
  // > Birthdate=29.02.2000, Age at 28.02.2012 is 11 years
} // CalculateAgeSamples

// ----------------------------------------------------------------------
public void PrintAge( DateTime birthDate, DateTime moment )
{
  Console.WriteLine( "Birthdate={0:d}, Age at {1:d} is {2} years", birthDate, moment, YearDiff( birthDate, moment ) );
} // PrintAge

我认为TimeSpan包含了我们所需要的一切,而不必求助于365.25(或任何其他近似值)。扩展Aug的示例:

DateTime myBD = new DateTime(1980, 10, 10);
TimeSpan difference = DateTime.Now.Subtract(myBD);

textBox1.Text = difference.Years + " years " + difference.Months + " Months " + difference.Days + " days";