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


当前回答

SQL版本:

declare @dd smalldatetime = '1980-04-01'
declare @age int = YEAR(GETDATE())-YEAR(@dd)
if (@dd> DATEADD(YYYY, -@age, GETDATE())) set @age = @age -1

print @age  

其他回答

我有一个定制的计算年龄的方法,加上一条奖金验证消息,以防有帮助:

public void GetAge(DateTime dob, DateTime now, out int years, out int months, out int days)
{
    years = 0;
    months = 0;
    days = 0;

    DateTime tmpdob = new DateTime(dob.Year, dob.Month, 1);
    DateTime tmpnow = new DateTime(now.Year, now.Month, 1);

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

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

    if (DateTime.IsLeapYear(dob.Year) && dob.Month == 2 && dob.Day == 29 && now >= new DateTime(now.Year, 3, 1))
        days++;

}   

private string ValidateDate(DateTime dob) //This method will validate the date
{
    int Years = 0; int Months = 0; int Days = 0;

    GetAge(dob, DateTime.Now, out Years, out Months, out Days);

    if (Years < 18)
        message =  Years + " is too young. Please try again on your 18th birthday.";
    else if (Years >= 65)
        message = Years + " is too old. Date of Birth must not be 65 or older.";
    else
        return null; //Denotes validation passed
}

方法调用此处并传递日期时间值(如果服务器设置为美国语言环境,则为MM/dd/yyyy)。将其替换为消息框或要显示的任何容器:

DateTime dob = DateTime.Parse("03/10/1982");  

string message = ValidateDate(dob);

lbldatemessage.Visible = !StringIsNullOrWhitespace(message);
lbldatemessage.Text = message ?? ""; //Ternary if message is null then default to empty string

记住,您可以按任何方式格式化邮件。

这可能会起作用:

public override bool IsValid(DateTime value)
{
    _dateOfBirth =  value;
    var yearsOld = (double) (DateTime.Now.Subtract(_dateOfBirth).TotalDays/365);
    if (yearsOld > 18)
        return true;
    return false;
}

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

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

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

这是一种奇怪的方法,但如果您将日期设置为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;
}
var birthDate = ... // DOB
var resultDate = DateTime.Now - birthDate;

使用resultDate,您可以应用TimeSpan财产来显示任何内容。