给定代表某人生日的DateTime,我如何计算他们的年龄(以年为单位)?
当前回答
var birthDate = ... // DOB
var resultDate = DateTime.Now - birthDate;
使用resultDate,您可以应用TimeSpan财产来显示任何内容。
其他回答
我花了一些时间研究这个问题,并用这个来计算某人的年龄,以年、月和日为单位。我已经针对2月29日的问题和闰年进行了测试,它似乎奏效了,我希望得到任何反馈:
public void 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 +=
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++;
}
}
我经常用手指数。我需要看一下日历,以确定事情何时发生变化。这就是我在代码中要做的:
int AgeNow(DateTime birthday)
{
return AgeAt(DateTime.Now, birthday);
}
int AgeAt(DateTime now, DateTime birthday)
{
return AgeAt(now, birthday, CultureInfo.CurrentCulture.Calendar);
}
int AgeAt(DateTime now, DateTime birthday, Calendar calendar)
{
// My age has increased on the morning of my
// birthday even though I was born in the evening.
now = now.Date;
birthday = birthday.Date;
var age = 0;
if (now <= birthday) return age; // I am zero now if I am to be born tomorrow.
while (calendar.AddYears(birthday, age + 1) <= now)
{
age++;
}
return age;
}
在LINQPad中运行此过程可获得以下结果:
PASSED: someone born on 28 February 1964 is age 4 on 28 February 1968
PASSED: someone born on 29 February 1964 is age 3 on 28 February 1968
PASSED: someone born on 31 December 2016 is age 0 on 01 January 2017
LINQPad中的代码在这里。
这个经典问题值得野田时间来解决。
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 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
我对Mark Soen的答案做了一个小小的修改:我重写了第三行,以便可以更容易地解析表达式。
public int AgeInYears(DateTime bday)
{
DateTime now = DateTime.Today;
int age = now.Year - bday.Year;
if (bday.AddYears(age) > now)
age--;
return age;
}
为了清晰起见,我还将其转换为函数。
推荐文章
- 实体框架核心:在上一个操作完成之前,在此上下文中开始的第二个操作
- 如何为构造函数定制Visual Studio的私有字段生成快捷方式?
- 为什么Visual Studio 2015/2017/2019测试运行器没有发现我的xUnit v2测试
- 如何使用JSON确保字符串是有效的JSON。网
- AppSettings从.config文件中获取值
- 通过HttpClient向REST API发布一个空体
- 如何检查IEnumerable是否为空或空?
- 自动化invokerrequired代码模式
- 解析日期字符串并更改格式
- 没有ListBox。SelectionMode="None",是否有其他方法禁用列表框中的选择?
- 在c#代码中设置WPF文本框的背景颜色
- 在c#中,什么是单子?
- c#和Java中的泛型有什么不同?和模板在c++ ?
- c#线程安全快速(est)计数器
- 如何将此foreach代码转换为Parallel.ForEach?