2012-05-16 4 views
3

Вот и проблема. Я видел много решений, но ни один не кажется, отвечают критериям, которые я хочу ...Как вы рассчитываете возраст в C#, используя дату рождения (учитывая високосные годы)

Я хочу, чтобы отобразить возраст в этом формате

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; 
} 

Любые идеи ???

UPDATE:

Я хочу, чтобы разница между этими двумя датами, как:

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); 
+0

возможно дубликат [Как рассчитать кого-то возраста в C#?] (Http://stackoverflow.com/questions/9/how-do-i-calculate-someones-age-in-c) – Magnus

+0

Это было задано слишком много раз, вы не нашли ни одного из них полезным? – V4Vendetta

+0

@ V4Vendetta, к сожалению, об этом никогда не спрашивали. Я имею в виду, проблема в другом, позвольте мне обновить мое описание ... –

ответ

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)); 
    } 
+0

так, будет ли это возвращать '20 y (s)', когда передано 'start = DateTime.Now.AddYears (-20)' и 'end = DateTime.Now'? Я сомневаюсь в этом. Я думаю, что он вернет 20 y (s) 5 d (s) –

+0

У меня есть много модульных тестов, охватывающих это. Он работает :) – HackedByChinese

+0

Обновлено, чтобы включить модульный тест для вашего примера. Я написал это для медицинского программного обеспечения, где пользователи были очень придирчивы к тому, как отображается возраст (приближения, предложенные в других ответах, не являются адекватными). – HackedByChinese

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; 

, чтобы получить желаемый результат.

+0

, который не даст мне никаких подробностей, соответствующих описанию выше ... :( –

+0

Это неверно для определения возраста, применимого к людям. – HackedByChinese

+0

Возможно, мне понадобится небольшое исправление в моем коде выше, если бы вы могли руководствоваться me ... –

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

Возраст в годах - это не проблема. Я хочу, чтобы возраст в годах, месяцах, днях –

+0

На самом деле не имеет смысла ... Подумайте об этом - два человека могут быть одинаковыми по возрасту в днях, но когда вы конвертируете их в годы, месяцы и дни, то количество месяцы и дни могут отличаться в зависимости от того, когда люди родились. Например, кто-то родился в феврале против кого-то, родившегося в январе. –

+0

ли это имеет смысл или нет, это требование пользователя :(Прошу прощения, но благодаря @HackedByChinese у меня есть мой ответ :) –

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; 
} 
+0

Это провалится в случае столетия или тысячелетия. Это дало бы только количество високосных лет, и каждый из них должен будет пройти цикл в течение столетий или тысячелетий, а затем добавить более логичную информацию о перекрытии века, тысячелетий и високосных лет ... –

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(); 
    } 

} 
+0

Добро пожаловать в StackOverflow! Ваш ответ действительно не затрагивает вопрос или, по крайней мере, не очень четко. Почитайте http://stackoverflow.com/questions/how-to-answer – Tass

Смежные вопросы