您如何使用出生日期计算C#的年龄(考虑闰年)

时间:2012-05-16 12:10:04

标签: c# asp.net .net c#-4.0 datetime

这是一个问题。我见过很多解决方案,但似乎没有人能达到我想要的标准......

我想以这种格式显示年龄

20 y(s) 2 m(s) 20 d(s)
20 y(s) 2 m(s)
2 m(s) 20 d(s)
20 d(s)

等...

我尝试了几种解决方案,但闰年对我造成了问题。由于闰年,我的单元测试总是失败,无论中间有多少天,飞跃都会计算额外的天数。

这是我的代码......

public static string AgeDiscription(DateTime dateOfBirth)
{
    var today = DateTime.Now;
    var days = GetNumberofDaysUptoNow(dateOfBirth);
    var months = 0;
    var years = 0;
    if (days > 365)
    {
        years = today.Year - dateOfBirth.Year;
        days = days % 365;
    }
    if (days > DateTime.DaysInMonth(today.Year, today.Month))
    {
        months = Math.Abs(today.Month - dateOfBirth.Month);
        for (int i = 0; i < months; i++)
        {
            days -= DateTime.DaysInMonth(today.Year, today.AddMonths(0 - i).Month);
        }
    }

    var ageDescription = new StringBuilder("");

    if (years != 0)
        ageDescription = ageDescription.Append(years + " y(s) ");
    if (months != 0)
        ageDescription = ageDescription.Append(months + " m(s) ");
    if (days != 0)
        ageDescription = ageDescription.Append(days + " d(s) ");

    return ageDescription.ToString();
}

public static int GetNumberofDaysUptoNow(DateTime dateOfBirth)
{
    var today = DateTime.Now;
    var timeSpan = today - dateOfBirth;
    var nDays = timeSpan.Days;
    return nDays;
}

任何想法???

更新

我希望两个日期之间的区别为:

var dateOfBirth = DateTime.Now.AddYears(-20);
string expected = "20 y(s) ";
string actual; // returns 20 y(s) 5 d(s)
actual = Globals.AgeDiscription(dateOfBirth);
Assert.AreEqual(expected, actual);

6 个答案:

答案 0 :(得分:6)

年龄相当棘手。这是我使用的结构的相关摘录。

public struct Age
{
    private readonly Int32 _years;
    private readonly Int32 _months;
    private readonly Int32 _days;
    private readonly Int32 _totalDays;

    /// <summary>
    /// Initializes a new instance of <see cref="Age"/>.
    /// </summary>
    /// <param name="start">The date and time when the age started.</param>
    /// <param name="end">The date and time when the age ended.</param>
    /// <remarks>This </remarks>
    public Age(DateTime start, DateTime end)
        : this(start, end, CultureInfo.CurrentCulture.Calendar)
    {
    }

    /// <summary>
    /// Initializes a new instance of <see cref="Age"/>.
    /// </summary>
    /// <param name="start">The date and time when the age started.</param>
    /// <param name="end">The date and time when the age ended.</param>
    /// <param name="calendar">Calendar used to calculate age.</param>
    public Age(DateTime start, DateTime end, Calendar calendar)
    {
        if (start > end) throw new ArgumentException("The starting date cannot be later than the end date.");

        var startDate = start.Date;
        var endDate = end.Date;

        _years = _months = _days = 0;
        _days += calendar.GetDayOfMonth(endDate) - calendar.GetDayOfMonth(startDate);
        if (_days < 0)
        {
            _days += calendar.GetDaysInMonth(calendar.GetYear(startDate), calendar.GetMonth(startDate));
            _months--;
        }
        _months += calendar.GetMonth(endDate) - calendar.GetMonth(startDate);
        if (_months < 0)
        {
            _months += calendar.GetMonthsInYear(calendar.GetYear(startDate));
            _years--;
        }
        _years += calendar.GetYear(endDate) - calendar.GetYear(startDate);

        var ts = endDate.Subtract(startDate);
        _totalDays = (Int32)ts.TotalDays;
    }

    /// <summary>
    /// Gets the number of whole years something has aged.
    /// </summary>
    public Int32 Years
    {
        get { return _years; }
    }

    /// <summary>
    /// Gets the number of whole months something has aged past the value of <see cref="Years"/>.
    /// </summary>
    public Int32 Months
    {
        get { return _months; }
    }

    /// <summary>
    /// Gets the age as an expression of whole months.
    /// </summary>
    public Int32 TotalMonths
    {
        get { return _years * 12 + _months; }
    }

    /// <summary>
    /// Gets the number of whole weeks something has aged past the value of <see cref="Years"/> and <see cref="Months"/>.
    /// </summary>
    public Int32 Days
    {
        get { return _days; }
    }

    /// <summary>
    /// Gets the total number of days that have elapsed since the start and end dates.
    /// </summary>
    public Int32 TotalDays
    {
        get { return _totalDays; }
    }

    /// <summary>
    /// Gets the number of whole weeks something has aged past the value of <see cref="Years"/> and <see cref="Months"/>.
    /// </summary>
    public Int32 Weeks
    {
        get { return (Int32) Math.Floor((Decimal) _days/7); }
    }

    /// <summary>
    /// Gets the age as an expression of whole weeks.
    /// </summary>
    public Int32 TotalWeeks
    {
        get { return (Int32) Math.Floor((Decimal) _totalDays/7); }
    }
}

这是一个通过的示例单元测试:

    [Test]
    public void Should_be_exactly_20_years_old()
    {
        var now = DateTime.Now;
        var age = new Age(now.AddYears(-20), now);

        Assert.That(age, Has.Property("Years").EqualTo(20)
            .And.Property("Months").EqualTo(0)
            .And.Property("Days").EqualTo(0));
    }

答案 1 :(得分:2)

使用

Timespan interval = DateTime.Now - DateOfBirth;

然后使用

interval.Days
interval.TotalDays;
interval.Hours;
interval.TotalHours;
interval.Minutes;
interval.TotalMinutes;
interval.Seconds;
interval.TotalSeconds;
interval.Milliseconds;
interval.TotalMilliseconds;
interval.Ticks;

获得理想的结果。

答案 2 :(得分:0)

static int AgeInYears(DateTime birthday, DateTime today)
{
    return ((today.Year - birthday.Year) * 372 + (today.Month - birthday.Month) * 31 + (today.Day - birthday.Day)) / 372;
}

答案 3 :(得分:0)

写下这个小函数,以获得当前年份和出生日期之间的闰年天数,并将返回的天数添加到您的年龄段的日期:

 private static int NumberOfLeapYears(int startYear, int endYear)
 {         
 int counter = 0;
 for (int year = startYear; year <= endYear; year++)
 counter += DateTime.IsLeapYear(year) ? 1 : 0;
 return counter;
 } 

答案 4 :(得分:0)

检查此代码:

{                                                    
    dif = int(datediff("D", Convert.ToDateTime("01/" + Q101m.text + "/" + Q101y.Text), (Convert.ToDateTime(Vdate.text)))/365.25)

    //If dif < 15 Or dif > 49 
    {
           MessageBox.Show("xxxxxxx");
           Q101m.Focus();
    }

}

答案 5 :(得分:0)

我在DateTime类中创建了一个扩展方法作为扩展方法,该方法是从@HackedByChinese“派生”的:

    /// <summary>
    /// Calculate age in years relative to months and days, for example Peters age is 25 years 2 months and 10 days
    /// </summary>
    /// <param name="startDate">The date when the age started</param>
    /// <param name="endDate">The date when the age ended</param>
    /// <param name="calendar">Calendar used to calculate age</param>
    /// <param name="years">Return number of years, with considering months and days</param>
    /// <param name="months">Return calculated months</param>
    /// <param name="days">Return calculated days</param>
    public static bool GetAge(this DateTime startDate, DateTime endDate, Calendar calendar, out int years, out int months, out int days)
    {
        if (startDate > endDate)
        {
            years = months = days = -1;
            return false;
        }

        years = months = days = 0;
        days += calendar.GetDayOfMonth(endDate) - calendar.GetDayOfMonth(startDate);

        // When negative select days of last month
        if (days < 0)
        {
            days += calendar.GetDaysInMonth(calendar.GetYear(startDate), calendar.GetMonth(startDate));
            months--;
        }

        months += calendar.GetMonth(endDate) - calendar.GetMonth(startDate);

        // when negative select month of last year
        if (months < 0)
        {
            months += calendar.GetMonthsInYear(calendar.GetYear(startDate));
            years--;
        }

        years += calendar.GetYear(endDate) - calendar.GetYear(startDate);

        return true;
    }

但是我认识到,结果天数可能与其他计算器有所不同。