给定一个代表一个人生日的DateTime
,如何计算他们的年龄?
给定一个代表一个人生日的DateTime
,如何计算他们的年龄?
一种易于理解和简单的解决方案。
// Save today's date.
var today = DateTime.Today;
// Calculate the age.
var age = today.Year - birthdate.Year;
// Go back to the year in which 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;
}
0
,不是1
。floor(8870 / 10000) == 0
。你在"计算"万位时,在8870
处是没有万位的。 - flindeberg
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
,因为这是唯一的原生方法来添加年份到闰年的2月29日并获得正确的结果,即普通年份的2月28日。DateTime
的扩展添加。通过这种方式,您可以以最简单的方式获得年龄:
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
}
date.Age(other)
? - marszedob.Age(toDay)
就会有很多意义。 - A.G.我的建议
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年的中国人,就这样。
需要解决的两个主要问题是:
1.准确计算年龄-以年,月,日等为单位。
2.计算一般认为的年龄 - 人们通常不关心自己的确切年龄,只关心今年生日是哪一天。
第一个问题的解决方案很明显:
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:
还有一个注意事项... 我会为此创建两个静态重载方法,一个用于通用使用,另一个用于友好使用:
public static int GetAge(DateTime bithDay, DateTime today)
{
//chosen solution method body
}
public static int GetAge(DateTime birthDay)
{
return GetAge(birthDay, DateTime.Now);
}
因为考虑到闰年等问题,我所知道的最好方法是:
DateTime birthDate = new DateTime(2000,3,1);
int age = (int)Math.Floor((DateTime.Now - birthDate).TotalDays / 365.25D);
这是一个一行代码:
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
,只是为了完整性。