给定代表某人生日的DateTime,我如何计算他们的年龄(以年为单位)?
当前回答
我强烈建议使用名为AgeCalculator的NuGet软件包,因为在计算年龄(闰年、时间成分等)时需要考虑很多事情,而且只有两行代码不能削减它。该库给您的时间不只是一年。它甚至在计算时考虑了时间成分,这样你就可以得到一个包含年、月、日和时间成分的准确年龄。更为先进的是,可以选择将2月29日作为闰年,而将2月28日作为非闰年。
其他回答
还有一个答案:
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=生日.Year,Mn=DateTime.Now.Month,Mb=生日.Month、Dn=DateTime.Now.Day,Db=生日.Day年龄=Yn-Yb+(31*(Mn-Mb)+(Dn-Db))/372我们知道,如果日期已经到达,我们需要的是Yn-Yb,如果日期尚未到达,则需要Yn-Yb-1。a) 如果Mn<Mb,我们有-341<=31*(Mn-Mb)<=-31和-30<=Dn-Db<=30-371<=31*(锰-Mb)+(Dn-Db)<=-1带整数除法(31*(Mn-Mb)+(Dn-Db))/372=-1b) 如果Mn=Mb和Dn<Db,则我们有31*(Mn-Mb)=0和-30<=Dn Db<=-1再次使用整数除法(31*(Mn-Mb)+(Dn-Db))/372=-1c) 如果Mn>Mb,我们有31<=31*(Mn-Mb)<=341和-30<=Dn-Db<=301<=31*(Mn-Mb)+(Dn-Db)<=371带整数除法(31*(Mn-Mb)+(Dn-Db))/372=0d) 如果Mn=Mb且Dn>Db,则我们有31*(Mn-Mb)=0且1<=Dn Db<=30再次使用整数除法(31*(Mn-Mb)+(Dn-Db))/372=0e) 如果Mn=Mb,Dn=Db,我们有31*(Mn-Mb)+Dn Db=0因此(31*(Mn-Mb)+(Dn-Db))/372=0
要使用最近的年龄计算年龄:
var ts = DateTime.Now - new DateTime(1988, 3, 19);
var age = Math.Round(ts.Days / 365.0);
人们可以这样计算“年龄”(即“西方人”的方式):
public static int AgeInYears(this System.DateTime source, System.DateTime target)
=> target.Year - source.Year is int age && age > 0 && source.AddYears(age) > target ? age - 1 : age < 0 && source.AddYears(age) < target ? age + 1 : age;
如果时间方向为“负”,则年龄也将为负。
可以添加一个分数,代表从目标到下一个生日的累计年龄:
public static double AgeInTotalYears(this System.DateTime source, System.DateTime target)
{
var sign = (source <= target ? 1 : -1);
var ageInYears = AgeInYears(source, target); // The method above.
var last = source.AddYears(ageInYears);
var next = source.AddYears(ageInYears + sign);
var fractionalAge = (double)(target - last).Ticks / (double)(next - last).Ticks * sign;
return ageInYears + fractionalAge;
}
分数是过去的时间(从上一个生日到下一个生日)与总时间的比率。
无论是向前还是向后,这两种方法都以相同的方式工作。
这里有一个非常简单且易于遵循的示例。
private int CalculateAge()
{
//get birthdate
DateTime dtBirth = Convert.ToDateTime(BirthDatePicker.Value);
int byear = dtBirth.Year;
int bmonth = dtBirth.Month;
int bday = dtBirth.Day;
DateTime dtToday = DateTime.Now;
int tYear = dtToday.Year;
int tmonth = dtToday.Month;
int tday = dtToday.Day;
int age = tYear - byear;
if (bmonth < tmonth)
age--;
else if (bmonth == tmonth && bday>tday)
{
age--;
}
return age;
}
这不是一个直接的答案,但更多的是从准科学的角度对当前问题进行哲学推理。
我认为,这个问题并没有具体说明衡量年龄的单位或文化,大多数答案似乎都假设了一个整数年表示。时间的国际单位制单位是秒,因此正确的通用答案应该是(当然,假设标准化日期时间,不考虑相对论效应):
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--;
在金融领域,当计算通常被称为日计数分数(Day Count Fraction)的东西时,也存在类似的问题,该分数大致是给定时期的年数。年龄问题确实是一个衡量时间的问题。
实际/实际(正确计算所有天数)惯例示例:
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;
另一种很常见的衡量时间的方法通常是“序列化”(命名这一日期惯例的家伙一定是认真的“trippin”):
DateTime start, end = .... // Whatever, assume start is before end
int days = (end - start).Days;
我想知道,在相对论年龄(以秒为单位)变得比迄今为止地球围绕太阳周期的粗略近似更有用之前,我们还需要多长时间:)或者换句话说,当一个周期必须给定一个位置或一个表示其自身运动的函数才能有效时:)