如何计算 C#中某人的年龄?

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

答案

一个易于理解和简单的解决方案。

// Save today's date.
var today = DateTime.Today;
// Calculate the age.
var age = today.Year - birthdate.Year;
// Go back to the year the person was born in case of a leap year
if (birthdate.Date > today.AddYears(-age)) age--;

但是,这假设您正在寻找西方的年龄观念,而不是使用东亚估算

这是一种奇怪的方法,但是如果您将日期格式设置为yyyymmdd并从当前日期中减去出生日期,然后删除年龄的最后 4 位数字:)

我不懂 C#,但是我相信这可以使用任何语言。

20080814 - 19800703 = 280111

删除最后 4 位数字 = 28

C#代码:

int now = int.Parse(DateTime.Now.ToString("yyyyMMdd"));
int dob = int.Parse(dateOfBirth.ToString("yyyyMMdd"));
int age = (now - dob) / 10000;

或者,也可以不使用扩展方法形式的所有类型转换。错误检查省略:

public static Int32 GetAge(this DateTime dateOfBirth)
{
    var today = DateTime.Today;

    var a = (today.Year * 100 + today.Month) * 100 + today.Day;
    var b = (dateOfBirth.Year * 100 + dateOfBirth.Month) * 100 + dateOfBirth.Day;

    return (a - b) / 10000;
}

我不知道如何接受错误的解决方案。正确的 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;
}

我认为到目前为止,没有任何答案提供不同的年龄计算文化。例如,参见东亚年龄估算与西方国家的估算

任何真正的答案都必须包括本地化。在此示例中, 策略模式可能是有序的。

对此的简单答案是应用如下所示的AddYears ,因为这是将 native 年 2 月 29 日加年并获得普通年 2 月 28 日正确结果的唯一本地方法。

有人认为 3 月 1 日是跨越式的生日,但是. Net 或任何官方规则都没有支持这一点,也没有通用的逻辑解释为什么 2 月份出生的人在另一个月份应该有其生日的 75%。

此外,Age 方法适合将自身添加为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
}

我的建议

int age = (int) ((DateTime.Now - bday).TotalDays/365.242199);

似乎在正确的日期更改了年份。 (我现场测试到 107 岁)

另一个功能,不是我自己的,而是在网上找到并进行了一些改进:

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 年的中国人:-)

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,因为它们会移动 years 年中的天数
  • 我已经增加了几行以提高可读性

请再注意一点... 我将为其创建 2 个静态重载方法,一种用于通用用法,第二种用于使用友好:

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

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

我参加晚会很晚,但是这里有一条线:

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

这是我们在这里使用的版本。它有效,而且非常简单。这与 Jeff 的想法相同,但我认为它更清楚一点,因为它将减法逻辑分开,因此更容易理解。

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

如果您认为这类事情不清楚,可以扩展三元运算符以使其更加清晰。

显然,这是作为DateTime的扩展方法完成的,但是显然,您可以抓住完成工作的那一行代码,并将其放在任何地方。在这里,为了完整性,传递DateTime.Now的 Extension 方法的另一个重载。