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


当前回答

这里有一个单行线:

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

其他回答

这是一个非常适合我的功能。没有计算,非常简单。

    public static string ToAge(this DateTime dob, DateTime? toDate = null)
    {
        if (!toDate.HasValue)
            toDate = DateTime.Now;
        var now = toDate.Value;

        if (now.CompareTo(dob) < 0)
            return "Future date";

        int years = now.Year - dob.Year;
        int months = now.Month - dob.Month;
        int days = now.Day - dob.Day;

        if (days < 0)
        {
            months--;
            days = DateTime.DaysInMonth(dob.Year, dob.Month) - dob.Day + now.Day;
        }

        if (months < 0)
        {
            years--;
            months = 12 + months;
        }


        return string.Format("{0} year(s), {1} month(s), {2} days(s)",
            years,
            months,
            days);
    }

这里是一个单元测试:

    [Test]
    public void ToAgeTests()
    {
        var date = new DateTime(2000, 1, 1);
        Assert.AreEqual("0 year(s), 0 month(s), 1 days(s)", new DateTime(1999, 12, 31).ToAge(date));
        Assert.AreEqual("0 year(s), 0 month(s), 0 days(s)", new DateTime(2000, 1, 1).ToAge(date));
        Assert.AreEqual("1 year(s), 0 month(s), 0 days(s)", new DateTime(1999, 1, 1).ToAge(date));
        Assert.AreEqual("0 year(s), 11 month(s), 0 days(s)", new DateTime(1999, 2, 1).ToAge(date));
        Assert.AreEqual("0 year(s), 10 month(s), 25 days(s)", new DateTime(1999, 2, 4).ToAge(date));
        Assert.AreEqual("0 year(s), 10 month(s), 1 days(s)", new DateTime(1999, 2, 28).ToAge(date));

        date = new DateTime(2000, 2, 15);
        Assert.AreEqual("0 year(s), 0 month(s), 28 days(s)", new DateTime(2000, 1, 18).ToAge(date));
    }
private int GetYearDiff(DateTime start, DateTime end)
{
    int diff = end.Year - start.Year;
    if (end.DayOfYear < start.DayOfYear) { diff -= 1; }
    return diff;
}
[Fact]
public void GetYearDiff_WhenCalls_ShouldReturnCorrectYearDiff()
{
    //arrange
    var now = DateTime.Now;
    //act
    //assert
    Assert.Equal(24, GetYearDiff(new DateTime(1992, 7, 9), now)); // passed
    Assert.Equal(24, GetYearDiff(new DateTime(1992, now.Month, now.Day), now)); // passed
    Assert.Equal(23, GetYearDiff(new DateTime(1992, 12, 9), now)); // passed
}

哇,我不得不在这里回答。。。这么简单的问题有很多答案。

private int CalcularIdade(DateTime dtNascimento)
    {
        var nHoje = Convert.ToInt32(DateTime.Today.ToString("yyyyMMdd"));
        var nAniversario = Convert.ToInt32(dtNascimento.ToString("yyyyMMdd"));

        double diff = (nHoje - nAniversario) / 10000;

        var ret = Convert.ToInt32(Math.Truncate(diff));

        return ret;
    }

为什么不能简化为检查出生日期?

第一行(var year=end.year-start.year-1;):假设出生日期尚未发生在结束年份。然后检查月份和日期,看看是否发生了;再增加一年。

对闰年情景没有特殊处理。如果不是闰年,你不能创建一个日期(2月29日)作为结束日期,所以如果结束日期是3月1日,而不是28日,生日庆祝活动将被计算在内。下面的函数将将此场景作为普通日期进行描述。

    static int Get_Age(DateTime start, DateTime end)
    {
        var year = end.Year - start.Year - 1;
        if (end.Month < start.Month)
            return year;
        else if (end.Month == start.Month)
        {
            if (end.Day >= start.Day)
                return ++year;
            return year;
        }
        else
            return ++year;
    }

    static void Test_Get_Age()
    {
        var start = new DateTime(2008, 4, 10); // b-date, leap year BTY
        var end = new DateTime(2023, 2, 1); // end date is before the b-date
        var result1 = Get_Age(start, end);
        var success1 = result1 == 14; // true

        end = new DateTime(2023, 4, 10); // end date is on the b-date
        var result2 = Get_Age(start, end);
        var success2 = result2 == 15; // true

        end = new DateTime(2023, 6, 22); // end date is after the b-date
        var result3 = Get_Age(start, end);
        var success3 = result3 == 15; // true

        start = new DateTime(2008, 2, 29); // b-date is on feb 29
        end = new DateTime(2023, 2, 28); // end date is before the b-date
        var result4 = Get_Age(start, end);
        var success4 = result4 == 14; // true

        end = new DateTime(2020, 2, 29); // end date is on the b-date, on another leap year
        var result5 = Get_Age(start, end);
        var success5 = result5 == 12; // true
    }

这是我们在这里使用的版本。它有效,而且相当简单。这与Jeff的想法相同,但我认为它更清晰一点,因为它分离了减法的逻辑,所以更容易理解。

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

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

显然,这是作为DateTime上的一个扩展方法完成的,但很明显,您可以抓取一行代码来完成工作并将其放在任何位置。这里我们有另一个传入DateTime的Extension方法重载。