2012-03-07 408 views
2

你好所以我實現了這個解決方案,從一個生日日期輸入獲得用戶的生日: Calculate age in C#生日年齡計算,而且數月的天數

這個偉大的工程,但是我確實需要解釋的生日的年齡不到一年(嬰兒,嬰兒)。如果當天和當前日期之間的時間少於365天,它現在只會給我一個「0」的年齡。

我在想什麼是這樣的:

public string calculateAge(DateTime birthDate, DateTime now) 
     { 
      //BDay is in different year (age > 1) 
      int age = now.Year - birthDate.Year; 
      if (now.Month < birthDate.Month || (now.Month == birthDate.Month && now.Day < birthDate.Day)) age--; 

      if (age == 0) 
      { 
       //Bday is in same year 
       age = now.Month - birthDate.Month; 
       if (now.Month < birthDate.Month || (now.Month == birthDate.Month && now.Day < birthDate.Day)) age--; 

       return age.ToString() + " months"; 
      } 
      if (age == 0) 
      { 
       //Bday is in the same month 
       age = now.Day - birthDate.Day; 
       if (now.Month < birthDate.Month || (now.Month == birthDate.Month && now.Day < birthDate.Day)) age--; 

       return age.ToString() + " days"; 
      } 
      return age.ToString(); 
     } 

但是我的一些測試Bdays的給我這個:

(Today's date: 3/6/2012) 
Bday1 = 3/5/2012 
Age result = -1 
Expected result = 1 day 

Bday2 = 3/1/2012 
Age result = 0 months 
Expected result = 5 days 

Bday3 = 1/1/2012 
Age result = 2 months 
Expected result = 2 months (this is fine) 

Bday4 = 3/7/2011 
Age result = -1 months 
Expected result = 11 months 

Bday5 = 3/1/2011 
Age result = 1 
Expected result = 1 (this is fine) 

你可以看到,因爲它是目前設置瞭如何問題源於bday月份小於當前月份的某些負數可能導致的結果。

我也看到關於不能進入「天」循環的錯誤,但我認爲這是一個毫無意義的問題。如果您對我可以做些什麼以獲得理想的結果有所瞭解,請告訴我。另外如果你需要更多的信息,比如測試bdays。謝謝!

回答

1
static public string calculateAge(DateTime birthDate, DateTime now) 
{ 
    birthDate = birthDate.Date; 
    now = now.Date; 

    var days = now.Day - birthDate.Day; 
    if (days < 0) 
    { 
    var newNow = now.AddMonths(-1); 
    days += (int)(now - newNow).TotalDays; 
    now = newNow; 
    } 
    var months = now.Month - birthDate.Month; 
    if (months < 0) 
    { 
    months += 12; 
    now = now.AddYears(-1); 
    } 
    var years = now.Year - birthDate.Year; 
    if (years == 0) 
    { 
    if (months == 0) 
     return days.ToString() + " days"; 
    else 
     return months.ToString() + " months"; 
    } 
    return years.ToString(); 
} 

結果(現在 - 2012/3/7):

3/5/2012: 2 days 
    3/1/2012: 6 days 
    1/1/2012: 2 months 
    3/8/2011: 11 months 
    3/1/2011: 1 
0

你可以有點接近這個功能,我發現:

/// <summary> 
/// Converts a timespan value to a string representation. 
/// </summary> 
/// <param name="time_span">the amount of time to convert to words</param> 
/// <param name="whole_seconds">round up the seconds</param> 
/// <returns>4 minutes, 58 seconds, etc</returns> 
/// <remarks>If it can't convert to a string, it returns "Calculating time remaining..."</remarks> 
public string TimespanToWords(TimeSpan time_span, bool whole_seconds = true) 
{ 
    TimeSpan span; 
    string str2 = ""; 
    if (time_span.Days > 0) 
    { 
     str2 = str2 + ", " + time_span.Days.ToString() + " days"; 
     span = new TimeSpan(time_span.Days, 0, 0, 0); 
     time_span = time_span.Subtract(span); 
    } 
    if (time_span.Hours > 0) 
    { 
     str2 = str2 + ", " + time_span.Hours.ToString() + " hours"; 
     span = new TimeSpan(0, time_span.Hours, 0, 0); 
     time_span = time_span.Subtract(span); 
    } 
    if (time_span.Minutes > 0) 
    { 
     str2 = str2 + ", " + time_span.Minutes.ToString() + " minutes"; 
     span = new TimeSpan(0, 0, time_span.Minutes, 0); 
     time_span = time_span.Subtract(span); 
    } 
    if (whole_seconds) 
    { 
     if (time_span.Seconds > 0) 
     { 
      str2 = str2 + ", " + time_span.Seconds.ToString() + " seconds"; 
     } 
    } 
    else 
    { 
     str2 = str2 + ", " + time_span.TotalSeconds.ToString() + " seconds"; 
    } 
    if (str2.Length > 0) 
    { 
     str2 = str2.Substring(2); 
    } 
    if (string.IsNullOrEmpty(str2)) 
    { 
     return "Calculating time remaining..."; 
    } 
    return str2; 
} 

下面是如何使用它:

var date1 = System.DateTime.Parse("01/01/1999"); 
    var date2 = System.DateTime.Parse("03/07/2012"); 


    var ts = date2 - date1; 

    var timeString = TimespanToWords(ts, true); 
1

實際上,我們有我們的框架中一個「DateSpan」結構做類似的計算...它的關鍵是你所追求的是低於哪裏通過一個定義的「開始」和「結束」DateTime變量它具有如下屬性:

public int WholeMonths 
    { 
     get 
     { 
      var startInEndsYear = Start.AddYears(End.Year - Start.Year); 

      // Are within a month of each other if EITHER: 
      // 1. Month is the same 
      // 2. Month period is within 1 
      // AND 
      // The difference between days of the year is less than the number of days in the start's month 
      var sameMonth = End.Month == startInEndsYear.Month || (End.Month - 1 == Start.Month && (End.DayOfYear - startInEndsYear.DayOfYear)/(double)DateTime.DaysInMonth(startInEndsYear.Year, startInEndsYear.Month) < 1.0d); 
      var sameMonthAndDay = sameMonth && End.Day == Start.Day; 

      var res = (End.Year - Start.Year) * 12; 
      if (sameMonth && !sameMonthAndDay) 
      { 
       res -= (startInEndsYear > End) ? 1 : 0; 
      } 
      else if (sameMonthAndDay) 
      { 
       res -= (End.TimeOfDay < Start.TimeOfDay ? 1 : 0); 
      } 
      else 
      { 
       res -= Start.Month; 
       res += End.Month; 
      } 
      return res; 
     } 
    } 
012對個

和從屬屬性:

public int WholeYears 
    { 
     get 
     { 
      return (int) Math.Floor(WholeMonths/12d); 
     } 
    } 

    public int PartMonths 
    { 
     get 
     { 
      return WholeMonths % 12; 
     } 
    } 

我會離開它作爲進一步的鍛鍊,爲您轉換成基於這些特性的話。

編輯:下面是各天的計算:

public TimeSpan PartDays 
    { 
     get 
     { 
      var startInEndsMonth = Start.AddMonths(WholeMonths); 
      return End.Subtract(startInEndsMonth); 
     } 
    } 
+0

上面並沒有考慮到 「天」。但是,將它留在這裏爲後代無論如何... – Reddog 2012-03-07 01:59:35

1

這裏有一種方法,其計算在西方文化中,一個正常人的年齡將會爲CE dates這樣做。不同的文化和日曆以不同的方式計算年齡。例如,China and other countries in Asia認爲一個新生嬰兒出生的那一天就是一歲,而他的年齡在中國農曆的每一個農曆新年都會記錄下來。所以如果一個孩子出生,比如在農曆新年前一個月,他會在那個月1歲,然後在他出生後的一個月內蜱達到2歲。

此算法不適用於BCE日期或從Julian轉換到公曆的日期。無論如何,無論如何分割它,這都是無稽之談,因爲不同的地點,即使在同一個國家內,也會在不同的時間切換:例如,直到布爾什維克革命之後,俄羅斯才改用格里曆。

enter image description here

所以除非你有開始日期的語言環境和結束日期的語言環境,你不能準確計算整個朱利安/格利高裏鴻溝的時間跨度。

的算法是:

  • 找到基準日,或在當前日期之前最近的月度生日。

    • 如果當天的最月是之前出生的實際日期,使用前一個月。如果實際出生日期晚於該月份的最後一天,請在當月的最後一天將其封頂。

      例如,如果當前日期爲2012年3月7日和實際生日是'31 1990' 年3月,您基準日是2月29日,2012年

  • 計算的區別在您的參考日期和年份和月份的出生日期之間。這很容易,因爲在西方日曆中,年份的數量持續數月。您可以使用整數除法:

    int totalMonths =(12 * endYear + endMonth) - (12 * startYear + startMonth); int年= totalMonths/12; int months = totalMonths%12;

或者你可以減去並在必要時攜帶。

int years = endYear - startYear ; 
int months = endMonth - startMonth ; 

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

結果在任何一種情況下應該是相同的。

天組件是從參考日期到當前日期的天數。

使用這種算法,在出生當天就是0天。

這裏是我的代碼:

static class HumanAgeFactory 
{ 

    public static HumanAge ComputeAge(this DateTime dob) 
    { 
    return dob.ComputeAgeAsOf(DateTime.Now) ; 
    } 

    public static HumanAge ComputeAgeAsOf(this DateTime dob , DateTime now) 
    { 
    dob = dob.Date ; // toss the time component 
    now = now.Date ; // toss the time component 

    if (dob > now) throw new ArgumentOutOfRangeException("dob" , "'now' must be on or after 'dob'") ; 

    DateTime mostRecentBirthDay = MostRecentNthDayOfTheMonthOnOrBefore(dob.Day , now) ; 
    int  years    = mostRecentBirthDay.Year - dob.Year   ; 
    int  months    = mostRecentBirthDay.Month - dob.Month   ; 
    int  days    = (int) (now - mostRecentBirthDay).TotalDays ; 

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

    if (days < 0) throw new InvalidOperationException() ; 
    if (months < 0) throw new InvalidOperationException() ; 
    if (years < 0) throw new InvalidOperationException() ; 

    HumanAge instance = new HumanAge(years , months , days) ; 
    return instance ; 
    } 

    private static DateTime MostRecentNthDayOfTheMonthOnOrBefore(int nthDay , DateTime now) 
    { 
    if (nthDay < 1) throw new ArgumentOutOfRangeException("dayOfBirth") ; 

    int year = now.Year ; 
    int month = now.Month ; 

    if (nthDay > now.Day) 
    { 
     --month ; 
     if (month < 1) 
     { 
     month += 12 ; 
     year -= 1 ; 
     } 
    } 

    int daysInMonth = CultureInfo.CurrentCulture.Calendar.GetDaysInMonth(year , month) ; 
    int day   = (nthDay > daysInMonth ? daysInMonth : nthDay) ; 

    DateTime instance = new DateTime(year , month , day) ; 
    return instance ; 
    } 

} 

public class HumanAge 
{ 
    public int Years { get ; private set ; } 
    public int Months { get ; private set ; } 
    public int Days { get ; private set ; } 

    public override string ToString() 
    { 
    string instance = string.Format("{0} {1} , {2} {3} , {4} {5}" , 
     Years , Years == 1 ? "year" : "years" , 
     Months , Months == 1 ? "month" : "months" , 
     Days , Days == 1 ? "day" : "days" 
    ) ; 
    return instance ; 
    } 

    public HumanAge(int years , int months , int days) 
    { 
    if (years < 0    ) throw new ArgumentOutOfRangeException("years" ) ; 
    if (months < 0 || months > 12) throw new ArgumentOutOfRangeException("months") ; 
    if (days < 0 || days > 31) throw new ArgumentOutOfRangeException("days" ) ; 

    this.Years = years ; 
    this.Months = months ; 
    this.Days = days ; 

    return ; 
    } 

} 
0
int[] getAge(DateTime dt) 
    { 
     DateTime today = DateTime.Now; 
     int years = 0; 
     int days = 0; 
     int months = 0; 
     int[] age = new int[3]; 
     while (dt.Year != today.Year || dt.Month != today.Month || dt.Day != today.Day) 
     { 
      if (dt.AddYears(1).CompareTo(today) <= 0) 
      { 
       years++; 
       dt = dt.AddYears(1); 
      } 
      else 
      { 
       if (dt.AddMonths(1).CompareTo(today) <= 0) 
       { 
        months++; 
        dt = dt.AddMonths(1); 
       } 
       else 
       { 
        if (dt.AddDays(1).CompareTo(today) <= 0) 
        { 
         days++; 
         dt = dt.AddDays(1); 
        } 
        else 
        { 
         dt = today; 
        } 
       } 

      } 
     } 
     age[0] = years; 
     age[1] = months; 
     age[2] = days; 
     return age; 
    } 
+0

這是正確的一個 – 2013-04-24 10:48:00

+0

嗨,歡迎來到堆棧溢出。你可以通過說明它的作用,它是如何解決問題的,並且可能列出與其他解決方案相比的好處來改進你的答案。爲了改進它,您可以點擊答案下的編輯按鈕。 – Ren 2013-04-24 11:01:59

2

您可以使用Time Period Library for .NET則DateDiff類:

// ---------------------------------------------------------------------- 
public void DateDiffSample() 
{ 
    DateTime date1 = new DateTime(2009, 11, 8, 7, 13, 59); 
    Console.WriteLine("Date1: {0}", date1); 
    // > Date1: 08.11.2009 07:13:59 
    DateTime date2 = new DateTime(2011, 3, 20, 19, 55, 28); 
    Console.WriteLine("Date2: {0}", date2); 
    // > Date2: 20.03.2011 19:55:28 

    DateDiff dateDiff = new DateDiff(date1, date2); 

    // elapsed 
    Console.WriteLine("DateDiff.ElapsedYears: {0}", dateDiff.ElapsedYears); 
    // > DateDiff.ElapsedYears: 1 
    Console.WriteLine("DateDiff.ElapsedMonths: {0}", dateDiff.ElapsedMonths); 
    // > DateDiff.ElapsedMonths: 4 
    Console.WriteLine("DateDiff.ElapsedDays: {0}", dateDiff.ElapsedDays); 
    // > DateDiff.ElapsedDays: 12 
} // DateDiffSample