C#では、DateTime型の誕生日に基づいて誰かの年齢を計算するにはどうすればよいですか?


1868

与えられたDateTime代表者の誕生日、どのように私は年間で自分の年齢を計算するのですか?


147
これまでの答えのすべてが見落としているのは、その人がどこで生まれ、どこにいるのかによって異なるということです。
Yaur

40
@Yaur:現在時刻+出産時刻をGMT / UTCに変換するだけです。年齢は相対的な値にすぎないため、タイムゾーンは関係ありません。ユーザーの現在のタイムゾーンを判別するには、GeoLocatingを使用できます。
Stefan Steiger、2011年

[ユリウス日] [1]を検討しませんか?[1]:stackoverflow.com/questions/7103064/...
モハメドHewedy

5
@Yaurのタイムゾーン間の計算に関する提案を考慮している場合、夏時間は計算に何らかの影響を与えるでしょうか?
DDM 2015

6
これは明らかに宿題であり、既存の試みは提供されなかったため、反対票を投じました。
マリー

回答:


2122

理解しやすくシンプルなソリューション。

// Save today's date.
var today = DateTime.Today;
// Calculate the age.
var age = today.Year - birthdate.Year;
// Go back to the year the person was born in case of a leap year
if (birthdate.Date > today.AddYears(-age)) age--;

ただし、これは、西アジアの年齢の考え方を探しており、東アジアの計算を使用していないことを前提としています。


252
DateTime.Nowのパフォーマンスについてコメントしたかっただけです。正確なタイムゾーン値が必要ない場合は、DateTime.UtcNowを使用するとはるかに高速になります。
JAG、

104
私たちが誕生日を話していることを考えると、時間の部分に関連性がないとすれば、DateTime.Todayを使用することができます。
Tristan Warner-Smith、

78
この回答は、すべてのロケールとすべての年齢で機能するわけではありません。ロシア(1918年)、ギリシャ(1924年)、トルコ(1926年)など、いくつかの国では、現在の居住者の誕生後の日付をスキップしています。
Lars D

30
実際、それはまだ完全に正しくはありません。このコードは、「bday」がDateTimeの日付部分であることを前提としています。それはエッジケースです(ほとんどの人は日付ではなく日付を渡すだけだと思います)が、誕生日が日時として00:00:00よりも大きい日時として渡された場合、 Danvilが指摘したバグにぶつかります。これを修正するには、bday = bday.Dateを設定します。
Øyvind

119
最後の行は私に考えすぎました。代わりにどのように:if(bday.AddYears(age)> now)age--; これはより直感的な表現のようです。
cdiggins

1015

これは奇妙な方法ですが、日付をフォーマット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;
}

5
実際、これは、datetime-fields(01-011900以降の合計日数)を含むMS-SQLでの使用に最適です
Patrik

5
@numerek提案された変更を独自の回答として投稿してください。それだけの価値があるのですが、現在の年に10000を掛けた値は、整数のオーバーフローに2桁の差はありません。20,150,000対2,147,483,648
GalacticCowboy

7
@LongChalk 20180101 - 20171231 = 8870。下4桁をドロップする0と、年齢が(暗黙的に)わかります。どうやって手に入れたの1
Rufus L

4
私はこれが古い答えであることを知っていますが、それから拡張メソッドを作成することはありません。そのようなロジックを定義するのに適切な場所ではありません。
ルッカフェッリ

1
これはどんな魔術ですか?
Muleskinner

391

テストスニペットは次のとおりです。

DateTime bDay = new DateTime(2000, 2, 29);
DateTime now = new DateTime(2009, 2, 28);
MessageBox.Show(string.Format("Test {0} {1} {2}",
                CalculateAgeWrong1(bDay, now),      // outputs 9
                CalculateAgeWrong2(bDay, now),      // outputs 9
                CalculateAgeCorrect(bDay, now),     // outputs 8
                CalculateAgeCorrect2(bDay, now)));  // outputs 8

ここにメソッドがあります:

public int CalculateAgeWrong1(DateTime birthDate, DateTime now)
{
    return new DateTime(now.Subtract(birthDate).Ticks).Year - 1;
}

public int CalculateAgeWrong2(DateTime birthDate, DateTime now)
{
    int age = now.Year - birthDate.Year;

    if (now < birthDate.AddYears(age))
        age--;

    return age;
}

public int CalculateAgeCorrect(DateTime birthDate, DateTime now)
{
    int age = now.Year - birthDate.Year;

    if (now.Month < birthDate.Month || (now.Month == birthDate.Month && now.Day < birthDate.Day))
        age--;

    return age;
}

public int CalculateAgeCorrect2(DateTime birthDate, DateTime now)
{
    int age = now.Year - birthDate.Year;

    // For leap years we need this
    if (birthDate > now.AddYears(-age)) 
        age--;
    // Don't use:
    // if (birthDate.AddYears(age) > now) 
    //     age--;

    return age;
}

33
このコードは機能しますが、うるう日に生まれた人は、2月28日ではなく3月1日にうるう年でない翌年の年齢に到達すると断言します。実際には、どちらのオプションも正しい場合がありますウィキペディアはこれについて何か言いたいことがあります。したがって、コードが「間違っている」わけではありませんが、どちらも受け入れられる解決策ではありません。
Matt Johnson-Pint 2014

18
@MattJohnson私はそれが実際正しいと思います。私のbdayが2月29日だった場合、2月28日はまだbdayを過ぎていません。私は2月27日と同じ年齢である必要があります。米国では、アルコールを販売する企業は、「YYYYでこの日以降に生まれた場合、アルコールは購入できません」(YYYYは毎年変更されます)のような兆候があります。2月29日に生まれた誰かが、彼らは21を回す年2月28日に、アルコールを購入することができないことを意味し(ほとんどの場所)、そして、彼らは3月1日まで、年上ではないという考えにサポートを貸すこと
jfren484

4
@ jfren484-ウィキペディアの記事を読んでください。法域によってかなり異なります。
Matt Johnson-Pint 2016

9
@ jfren484あなたの主張は哲学とはまったく関係がありません。しかし、すべてはあなた自身の個人的な感情と関係があります。2月29日に生まれた人が「法定年齢の境界」を形成しない限り、「年齢」はほとんど重要ではありません(例:アルコールの購入、投票、年金、軍への加入、運転免許の取得)。米国の飲酒年齢(21歳)を検討してください。ほとんどの人は7670日です。うるう年の2月29日より前、またはうるう年の3月1日から生まれた場合は、7671日です。2月29日に生まれた場合:2月28日は7670日、3月1日は7671日です。どちらを選択してもかまいません。
幻滅

4
@CraigYoungあなたは私が哲学的に何を意味しているか理解していない。私はその用語を合法的なものと対照的に使用しました。人の法定年齢を知る必要があるアプリケーションを書いている場合、彼らが知る必要があるのは、そのアプリケーションが2月29日に生まれた人々の治療にどのように使用されるかを知ることだけです。ただし、それどのように扱われるべきかについて話し、それは定義により、哲学です。そして、はい、私が与えた意見は私自身の意見ですが、私はそれが2月28ためになるよりも、3月1日を主張する方が簡単だと思う、私が言ったように
jfren484

110

これに対する単純な答えAddYearsは、うるう年の2月29日に年を追加し、一般的な年の2月28日の正しい結果を取得する唯一のネイティブメソッドであるため、以下に示すように適用することです。

3月1日は跳躍の誕生日であると感じる人もいますが、.Netも公式ルールもこれをサポートしておらず、2月生まれの人が別の月に75%の誕生日を迎える理由を説明する一般的なロジックもありません。

さらに、Ageメソッドは、への拡張として追加するのに適していDateTimeます。これにより、最も簡単な方法で年齢を取得できます。

  1. リストアイテム

int age = birthDate.Age();

public static class DateTimeExtensions
{
    /// <summary>
    /// Calculates the age in years of the current System.DateTime object today.
    /// </summary>
    /// <param name="birthDate">The date of birth</param>
    /// <returns>Age in years today. 0 is returned for a future date of birth.</returns>
    public static int Age(this DateTime birthDate)
    {
        return Age(birthDate, DateTime.Today);
    }

    /// <summary>
    /// Calculates the age in years of the current System.DateTime object on a later date.
    /// </summary>
    /// <param name="birthDate">The date of birth</param>
    /// <param name="laterDate">The date on which to calculate the age.</param>
    /// <returns>Age in years on a later day. 0 is returned as minimum.</returns>
    public static int Age(this DateTime birthDate, DateTime laterDate)
    {
        int age;
        age = laterDate.Year - birthDate.Year;

        if (age > 0)
        {
            age -= Convert.ToInt32(laterDate.Date < birthDate.Date.AddYears(age));
        }
        else
        {
            age = 0;
        }

        return age;
    }
}

次に、このテストを実行します。

class Program
{
    static void Main(string[] args)
    {
        RunTest();
    }

    private static void RunTest()
    {
        DateTime birthDate = new DateTime(2000, 2, 28);
        DateTime laterDate = new DateTime(2011, 2, 27);
        string iso = "yyyy-MM-dd";

        for (int i = 0; i < 3; i++)
        {
            for (int j = 0; j < 3; j++)
            {
                Console.WriteLine("Birth date: " + birthDate.AddDays(i).ToString(iso) + "  Later date: " + laterDate.AddDays(j).ToString(iso) + "  Age: " + birthDate.AddDays(i).Age(laterDate.AddDays(j)).ToString());
            }
        }

        Console.ReadKey();
    }
}

重要な日付の例は次のとおりです。

生年月日:2000-02-29後日:2011-02-28年齢:11

出力:

{
    Birth date: 2000-02-28  Later date: 2011-02-27  Age: 10
    Birth date: 2000-02-28  Later date: 2011-02-28  Age: 11
    Birth date: 2000-02-28  Later date: 2011-03-01  Age: 11
    Birth date: 2000-02-29  Later date: 2011-02-27  Age: 10
    Birth date: 2000-02-29  Later date: 2011-02-28  Age: 11
    Birth date: 2000-02-29  Later date: 2011-03-01  Age: 11
    Birth date: 2000-03-01  Later date: 2011-02-27  Age: 10
    Birth date: 2000-03-01  Later date: 2011-02-28  Age: 10
    Birth date: 2000-03-01  Later date: 2011-03-01  Age: 11
}

そして、後日2012-02-28:

{
    Birth date: 2000-02-28  Later date: 2012-02-28  Age: 12
    Birth date: 2000-02-28  Later date: 2012-02-29  Age: 12
    Birth date: 2000-02-28  Later date: 2012-03-01  Age: 12
    Birth date: 2000-02-29  Later date: 2012-02-28  Age: 11
    Birth date: 2000-02-29  Later date: 2012-02-29  Age: 12
    Birth date: 2000-02-29  Later date: 2012-03-01  Age: 12
    Birth date: 2000-03-01  Later date: 2012-02-28  Age: 11
    Birth date: 2000-03-01  Later date: 2012-02-29  Age: 11
    Birth date: 2000-03-01  Later date: 2012-03-01  Age: 12
}

4
3月1日に2月29日の誕生日を迎えること、厳密には28日に誕生日を迎えることに関するコメントは早すぎます(実際には1日早い)。1日は1日遅すぎます。しかし、誕生日はその間なので、うるう年以外の年の年齢を計算するために1日を使用することは、私にとってより理にかなっています。
Cyber​​Claw 2018

1
ソフトウェア設計の観点から、これを拡張メソッドとして書くことは、私にはあまり意味がありません。date.Age(other)
marsze

90

私のおすすめ

int age = (int) ((DateTime.Now - bday).TotalDays/365.242199);

その年は正しい日に変わります。(私は107歳までスポットテストしました。)


26
:私はハリー・パッチがあなたのスポットテストの方法論高く評価しているとは思わない latimes.com/news/obituaries/...
MusiGenesis

3
グーグルは言うdays in a year = 365.242199
mpen

12
グレゴリオ暦の1年の平均の長さは365.2425日です。
dan04

4
これは最も簡単な解決策の1つであり、それで十分です。私が私のX歳の誕生日の半日前にプログラムが私がX歳であると言っているかどうかは誰が気にします。数学的にではないが、プログラムは多かれ少なかれ正しい。私はこのソリューションが本当に好きです。
PeterPerháč

13
^^時にはそれが重要だからです。私のテストでは、これは人の誕生日に失敗し、彼らが彼らよりも若いと報告しています。
ChadT

76

別の機能、私ではなく、ウェブ上で見つかり、少し洗練されました:

public static int GetAge(DateTime birthDate)
{
    DateTime n = DateTime.Now; // To avoid a race condition around midnight
    int age = n.Year - birthDate.Year;

    if (n.Month < birthDate.Month || (n.Month == birthDate.Month && n.Day < birthDate.Day))
        age--;

    return age;
}

頭に浮かぶのは2つだけです。グレゴリオ暦を使用していない国の人々はどうですか?DateTime.Nowは、サーバー固有のカルチャにあると思います。私は実際にアジアのカレンダーを操作することについてはまったく知識がなく、カレンダー間で日付を変換する簡単な方法があるかどうかわかりませんが、万が一4660年以降の中国人について疑問に思っている場合はどうでしょうか:-)


これは、さまざまな地域(日付形式)を最適に処理するようです。
webdad3 2016年

53

2解決すべき主な問題は次のとおりです。

1.正確な年齢を計算 -年、月、日などで

2.一般的に認識されている年齢を計算する -人々は通常、自分が正確に何歳であるかを気にせず、現在の年の誕生日がいつかを気にします。


1の解決策は明らかです。

DateTime birth = DateTime.Parse("1.1.2000");
DateTime today = DateTime.Today;     //we usually don't care about birth time
TimeSpan age = today - birth;        //.NET FCL should guarantee this as precise
double ageInDays = age.TotalDays;    //total number of days ... also precise
double daysInYear = 365.2425;        //statistical value for 400 years
double ageInYears = ageInDays / daysInYear;  //can be shifted ... not so precise

2の解決策は、総年齢を決定するのにそれほど正確ではないものですが、人々によって正確であると認識されています。また、年齢を「手動」で計算する場合にも、この値を使用します。

DateTime birth = DateTime.Parse("1.1.2000");
DateTime today = DateTime.Today;
int age = today.Year - birth.Year;    //people perceive their age in years

if (today.Month < birth.Month ||
   ((today.Month == birth.Month) && (today.Day < birth.Day)))
{
  age--;  //birthday in current year not yet reached, we are 1 year younger ;)
          //+ no birthday for 29.2. guys ... sorry, just wrong date for birth
}

2.の注:

  • これは私の好ましい解決策です
  • うるう年の日数をシフトするため、DateTime.DayOfYearまたはTimeSpansは使用できません。
  • 読みやすくするためにもう少し行を追加しました

もう1つ注意してください... 2つの静的なオーバーロードメソッドを作成します。1つは汎用的な使用法、もう1つは使用法にやさしい方法です。

public static int GetAge(DateTime bithDay, DateTime today) 
{ 
  //chosen solution method body
}

public static int GetAge(DateTime birthDay) 
{ 
  return GetAge(birthDay, DateTime.Now);
}

50

ここにワンライナーがあります:

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

23
これは壊れています。テスト可能にした:public static int CalculateAge(DateTime dateOfBirth、DateTime dateToCalculateAge){return new DateTime(dateToCalculateAge.Subtract(dateOfBirth).Ticks).Year-1; } ... 1990-06-01を入力して14歳の誕生日(1990-05-31)の前の日に年齢を計算すると、14歳になります。
Kjensen

43

ここで使用するバージョンです。それは機能し、それはかなり簡単です。それはジェフと同じ考えですが、それは1を引くためのロジックを分離するので、それは少しわかりやすいので、もう少し明確だと思います。

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

種類が不明な場合は、3項演算子を拡張してさらに明確にすることができます。

明らかにこれはの拡張メソッドとして行われDateTimeますが、作業を行うコードの1行を取得してどこにでも置くことができるのは明らかです。ここではDateTime.Now、完全を期すために、を渡すExtensionメソッドの別のオーバーロードがあります。


6
これは、dateOfBirthまたはdateAsAtのいずれかがうるう年に該当する場合、1日ずれることがあると思います。2003年3月1日に2004年2月29日に生まれた人の年齢を考えます。これを修正するには、(Month、DayOfMonth)ペアの辞書式比較を行い、それを条件式に使用する必要があります。
Doug McClean

1
また、誕生日の時点で適切な年齢を表示することもできません。
dotjoe 2009年

43

うるう年とすべてのために私が知っている最良の方法は次のとおりです。

DateTime birthDate = new DateTime(2000,3,1);
int age = (int)Math.Floor((DateTime.Now - birthDate).TotalDays / 365.25D);

34

私はこれを使います:

public static class DateTimeExtensions
{
    public static int Age(this DateTime birthDate)
    {
        return Age(birthDate, DateTime.Now);
    }

    public static int Age(this DateTime birthDate, DateTime offsetDate)
    {
        int result=0;
        result = offsetDate.Year - birthDate.Year;

        if (offsetDate.DayOfYear < birthDate.DayOfYear)
        {
              result--;
        }

        return result;
    }
}

32

これにより、この質問の「詳細」がわかります。多分これはあなたが探しているものです

DateTime birth = new DateTime(1974, 8, 29);
DateTime today = DateTime.Now;
TimeSpan span = today - birth;
DateTime age = DateTime.MinValue + span;

// Make adjustment due to MinValue equalling 1/1/1
int years = age.Year - 1;
int months = age.Month - 1;
int days = age.Day - 1;

// Print out not only how many years old they are but give months and days as well
Console.Write("{0} years, {1} months, {2} days", years, months, days);

1
これは常に機能するとは限りません。DateTime.MinValueにSpanを追加すると、うるう年などが考慮されないため、ブール値が機能する可能性があります。AddYears()、AddMonths、およびAddDays()関数を使用して年、月、日をAgeに追加すると、常にDatetimeが返されるとは限りません現在の日付。
Athanasios Kataras 2013年

3
タイムスパン自体は、2つの日付の間のうるう年を自動的に考慮しているので、何が起こっているのかわかりません。私はマイクロソフトフォーラムで質問しましたが、マイクロソフトでは、2つの日付間のうるう年を考慮に入れていることを確認しました。
ジャクリーンロリオール2013年

2
次の2つのシナリオを考えてみましょう。最初のDateTime.Nowは2001年1月1日で、子供は2000年1月1日に生まれます。2000年はうるう年であり、結果は1年、0か月、1日になります。2番目のセナリオンでは、DateTime.Nowは1/1/2002で、子供は2001年1月1日に生まれます。この場合、結果は1年、0か月、0日になります。これは、うるう年以外の期間を追加するために発生します。DateTime.MinValueがうるう年の場合、結果は最初の1年で0年11か月と30日になります。(コードで試してください)。
Athanasios Kataras 2013年

1
賛成投票!私はほぼ同じソリューションを思いつきました(+の代わりにDateTime.MinValue.AddTicks(span.Ticks)を使用しましたが、結果は同じであり、あなたのコードは数文字少ないコードです)。
誠さん2015年

4
そうではありません。しかし、それが結果だとすれば。なぜそれが重要なのですか?そうではありません。どちらの場合も、飛躍するかどうかは、これが機能しない例があります。それを見せたかった。DIFFは正しいです。Spanはうるう年を考慮に入れます。しかし、基準日への追加はそうではありません。コード内の例を試してみてください。そうすれば、私が正しいことがわかります。
Athanasios Kataras

28

SQL Serverのユーザー定義関数を作成して、誕生日を指定して誰かの年齢を計算しました。これは、クエリの一部として必要な場合に役立ちます。

using System;
using System.Data;
using System.Data.Sql;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;

public partial class UserDefinedFunctions
{
    [SqlFunction(DataAccess = DataAccessKind.Read)]
    public static SqlInt32 CalculateAge(string strBirthDate)
    {
        DateTime dtBirthDate = new DateTime();
        dtBirthDate = Convert.ToDateTime(strBirthDate);
        DateTime dtToday = DateTime.Now;

        // get the difference in years
        int years = dtToday.Year - dtBirthDate.Year;

        // subtract another year if we're before the
        // birth day in the current year
        if (dtToday.Month < dtBirthDate.Month || (dtToday.Month == dtBirthDate.Month && dtToday.Day < dtBirthDate.Day))
            years=years-1;

        int intCustomerAge = years;
        return intCustomerAge;
    }
};

28

ここにさらに別の答えがあります:

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

これは広範囲にユニットテストされています。少し「魔法」に見えます。372は、毎月31日の場合の1年の日数です。

それが機能する理由の説明(ここから削除)は次のとおりです。

設定しましょう Yn = DateTime.Now.Year, Yb = birthday.Year, Mn = DateTime.Now.Month, Mb = birthday.Month, Dn = DateTime.Now.Day, Db = birthday.Day

age = Yn - Yb + (31*(Mn - Mb) + (Dn - Db)) / 372

必要なのはYn-Yb、日付にすでに達しているかどうか、Yn-Yb-1そうでない場合です。

a)の場合Mn<Mb-341 <= 31*(Mn-Mb) <= -31 and -30 <= Dn-Db <= 30

-371 <= 31*(Mn - Mb) + (Dn - Db) <= -1

整数除算あり

(31*(Mn - Mb) + (Dn - Db)) / 372 = -1

b)の場合Mn=MbDn<Db、我々が持っています31*(Mn - Mb) = 0 and -30 <= Dn-Db <= -1

整数除算で、再び

(31*(Mn - Mb) + (Dn - Db)) / 372 = -1

c)の場合Mn>Mb31 <= 31*(Mn-Mb) <= 341 and -30 <= Dn-Db <= 30

1 <= 31*(Mn - Mb) + (Dn - Db) <= 371

整数除算あり

(31*(Mn - Mb) + (Dn - Db)) / 372 = 0

d)の場合Mn=MbDn>Db、我々が持っている31*(Mn - Mb) = 0 and 1 <= Dn-Db <= 30

整数除算で、再び

(31*(Mn - Mb) + (Dn - Db)) / 372 = 0

e)の場合Mn=MbDn=Db、我々が持っています31*(Mn - Mb) + Dn-Db = 0

したがって (31*(Mn - Mb) + (Dn - Db)) / 372 = 0


3
私はこの長くて面倒な議論に出くわしました、そしてあなたの解決策は本当に素晴らしくて小さなアプローチです。シンプルにしていただきありがとうございます
nabuchodonossor

25

私はこれに取り組んで少し時間を費やして、これを思いついて、年、月、日で誰かの年齢を計算しました。2月29日の問題とうるう年に対してテストしましたが、うまくいくようです。フィードバックをいただければ幸いです。

public void LoopAge(DateTime myDOB, DateTime FutureDate)
{
    int years = 0;
    int months = 0;
    int days = 0;

    DateTime tmpMyDOB = new DateTime(myDOB.Year, myDOB.Month, 1);

    DateTime tmpFutureDate = new DateTime(FutureDate.Year, FutureDate.Month, 1);

    while (tmpMyDOB.AddYears(years).AddMonths(months) < tmpFutureDate)
    {
        months++;

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

    if (FutureDate.Day >= myDOB.Day)
    {
        days = days + FutureDate.Day - myDOB.Day;
    }
    else
    {
        months--;

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

        days +=
            DateTime.DaysInMonth(
                FutureDate.AddMonths(-1).Year, FutureDate.AddMonths(-1).Month
            ) + FutureDate.Day - myDOB.Day;

    }

    //add an extra day if the dob is a leap day
    if (DateTime.IsLeapYear(myDOB.Year) && myDOB.Month == 2 && myDOB.Day == 29)
    {
        //but only if the future date is less than 1st March
        if (FutureDate >= new DateTime(FutureDate.Year, 3, 1))
            days++;
    }

}

21

1歳未満の人を考慮する必要がありますか?中国の文化として、小さな赤ちゃんの年齢を2か月または4週間と説明しています。

以下は私の実装ですが、特に2/28のような日付を処理することは、私が想像したほど単純ではありません。

public static string HowOld(DateTime birthday, DateTime now)
{
    if (now < birthday)
        throw new ArgumentOutOfRangeException("birthday must be less than now.");

    TimeSpan diff = now - birthday;
    int diffDays = (int)diff.TotalDays;

    if (diffDays > 7)//year, month and week
    {
        int age = now.Year - birthday.Year;

        if (birthday > now.AddYears(-age))
            age--;

        if (age > 0)
        {
            return age + (age > 1 ? " years" : " year");
        }
        else
        {// month and week
            DateTime d = birthday;
            int diffMonth = 1;

            while (d.AddMonths(diffMonth) <= now)
            {
                diffMonth++;
            }

            age = diffMonth-1;

            if (age == 1 && d.Day > now.Day)
                age--;

            if (age > 0)
            {
                return age + (age > 1 ? " months" : " month");
            }
            else
            {
                age = diffDays / 7;
                return age + (age > 1 ? " weeks" : " week");
            }
        }
    }
    else if (diffDays > 0)
    {
        int age = diffDays;
        return age + (age > 1 ? " days" : " day");
    }
    else
    {
        int age = diffDays;
        return "just born";
    }
}

この実装はテストケースを下回っています。

[TestMethod]
public void TestAge()
{
    string age = HowOld(new DateTime(2011, 1, 1), new DateTime(2012, 11, 30));
    Assert.AreEqual("1 year", age);

    age = HowOld(new DateTime(2011, 11, 30), new DateTime(2012, 11, 30));
    Assert.AreEqual("1 year", age);

    age = HowOld(new DateTime(2001, 1, 1), new DateTime(2012, 11, 30));
    Assert.AreEqual("11 years", age);

    age = HowOld(new DateTime(2012, 1, 1), new DateTime(2012, 11, 30));
    Assert.AreEqual("10 months", age);

    age = HowOld(new DateTime(2011, 12, 1), new DateTime(2012, 11, 30));
    Assert.AreEqual("11 months", age);

    age = HowOld(new DateTime(2012, 10, 1), new DateTime(2012, 11, 30));
    Assert.AreEqual("1 month", age);

    age = HowOld(new DateTime(2008, 2, 28), new DateTime(2009, 2, 28));
    Assert.AreEqual("1 year", age);

    age = HowOld(new DateTime(2008, 3, 28), new DateTime(2009, 2, 28));
    Assert.AreEqual("11 months", age);

    age = HowOld(new DateTime(2008, 3, 28), new DateTime(2009, 3, 28));
    Assert.AreEqual("1 year", age);

    age = HowOld(new DateTime(2009, 1, 28), new DateTime(2009, 2, 28));
    Assert.AreEqual("1 month", age);

    age = HowOld(new DateTime(2009, 2, 1), new DateTime(2009, 3, 1));
    Assert.AreEqual("1 month", age);

    // NOTE.
    // new DateTime(2008, 1, 31).AddMonths(1) == new DateTime(2009, 2, 28);
    // new DateTime(2008, 1, 28).AddMonths(1) == new DateTime(2009, 2, 28);
    age = HowOld(new DateTime(2009, 1, 31), new DateTime(2009, 2, 28));
    Assert.AreEqual("4 weeks", age);

    age = HowOld(new DateTime(2009, 2, 1), new DateTime(2009, 2, 28));
    Assert.AreEqual("3 weeks", age);

    age = HowOld(new DateTime(2009, 2, 1), new DateTime(2009, 3, 1));
    Assert.AreEqual("1 month", age);

    age = HowOld(new DateTime(2012, 11, 5), new DateTime(2012, 11, 30));
    Assert.AreEqual("3 weeks", age);

    age = HowOld(new DateTime(2012, 11, 1), new DateTime(2012, 11, 30));
    Assert.AreEqual("4 weeks", age);

    age = HowOld(new DateTime(2012, 11, 20), new DateTime(2012, 11, 30));
    Assert.AreEqual("1 week", age);

    age = HowOld(new DateTime(2012, 11, 25), new DateTime(2012, 11, 30));
    Assert.AreEqual("5 days", age);

    age = HowOld(new DateTime(2012, 11, 29), new DateTime(2012, 11, 30));
    Assert.AreEqual("1 day", age);

    age = HowOld(new DateTime(2012, 11, 30), new DateTime(2012, 11, 30));
    Assert.AreEqual("just born", age);

    age = HowOld(new DateTime(2000, 2, 29), new DateTime(2009, 2, 28));
    Assert.AreEqual("8 years", age);

    age = HowOld(new DateTime(2000, 2, 29), new DateTime(2009, 3, 1));
    Assert.AreEqual("9 years", age);

    Exception e = null;

    try
    {
        age = HowOld(new DateTime(2012, 12, 1), new DateTime(2012, 11, 30));
    }
    catch (ArgumentOutOfRangeException ex)
    {
        e = ex;
    }

    Assert.IsTrue(e != null);
}

お役に立てれば幸いです。


20

それをシンプルに保つ(そしておそらく愚か:))。

DateTime birth = new DateTime(1975, 09, 27, 01, 00, 00, 00);
TimeSpan ts = DateTime.Now - birth;
Console.WriteLine("You are approximately " + ts.TotalSeconds.ToString() + " seconds old.");

TimeSpanは最初の選択肢でしたが、TotalYearsプロパティを提供していないことがわかりました。(ts.TotalDays / 365)を試すこともできますが、うるう年などは考慮されません
Lazlow

19

私が見つけた最も簡単な方法はこれです。これは、米国および西ヨーロッパのロケールで正しく機能します。他のロケール、特に中国のような場所と話すことはできません。年齢の最初の計算に続いて、最大4つの余分な比較が行われます。

public int AgeInYears(DateTime birthDate, DateTime referenceDate)
{
  Debug.Assert(referenceDate >= birthDate, 
               "birth date must be on or prior to the reference date");

  DateTime birth = birthDate.Date;
  DateTime reference = referenceDate.Date;
  int years = (reference.Year - birth.Year);

  //
  // an offset of -1 is applied if the birth date has 
  // not yet occurred in the current year.
  //
  if (reference.Month > birth.Month);
  else if (reference.Month < birth.Month) 
    --years;
  else // in birth month
  {
    if (reference.Day < birth.Day)
      --years;
  }

  return years ;
}

私はこれに対する答えを調べていて、うるう日の出産の規制/法的意味について誰も言及していないことに気づきました。たとえば、Wikipediaによると、2月29日にさまざまな法域で生まれた場合、うるう年以外の誕生日は次のように異なります。

  • イギリスと香港の場合:それはその年の通常の日なので、翌日、3月1日はあなたの誕生日です。
  • ニュージーランド:前日、運転免許証のための2月28日、その他の目的のための3月1日です。
  • 台湾:2月28日です。

そして、私が知る限りでは、米国では、法令はこの問題について沈黙しており、コモンローとさまざまな規制機関が規制で物事をどのように定義するかに任せています。

そのために、改善:

public enum LeapDayRule
{
  OrdinalDay     = 1 ,
  LastDayOfMonth = 2 ,
}

static int ComputeAgeInYears(DateTime birth, DateTime reference, LeapYearBirthdayRule ruleInEffect)
{
  bool isLeapYearBirthday = CultureInfo.CurrentCulture.Calendar.IsLeapDay(birth.Year, birth.Month, birth.Day);
  DateTime cutoff;

  if (isLeapYearBirthday && !DateTime.IsLeapYear(reference.Year))
  {
    switch (ruleInEffect)
    {
      case LeapDayRule.OrdinalDay:
        cutoff = new DateTime(reference.Year, 1, 1)
                             .AddDays(birth.DayOfYear - 1);
        break;

      case LeapDayRule.LastDayOfMonth:
        cutoff = new DateTime(reference.Year, birth.Month, 1)
                             .AddMonths(1)
                             .AddDays(-1);
        break;

      default:
        throw new InvalidOperationException();
    }
  }
  else
  {
    cutoff = new DateTime(reference.Year, birth.Month, birth.Day);
  }

  int age = (reference.Year - birth.Year) + (reference >= cutoff ? 0 : -1);
  return age < 0 ? 0 : age;
}

このコードは以下を前提としていることに注意してください:

  • 西洋(ヨーロッパ)の年齢の計算、および
  • グレゴリオ暦のように、月の終わりにうるう日を1つ挿入するカレンダー。

19
TimeSpan diff = DateTime.Now - birthdayDateTime;
string age = String.Format("{0:%y} years, {0:%M} months, {0:%d}, days old", diff);

どれだけ正確に返してほしいかわからないので、読みやすい文字列を作成しました。


18

これは直接的な答えではありませんが、準科学的見地からの当面の問題に関する哲学的推論の詳細です。

質問は年齢を測定する単位や文化を指定していないと私は主張しますが、ほとんどの回答は整数の年次表現を想定しているようです。時間のSI単位はsecondergoです。正しい一般的な答えは次のとおりです(もちろん、正規化されているDateTimeと仮定し、相対論的効果をまったく考慮していません)。

var lifeInSeconds = (DateTime.Now.Ticks - then.Ticks)/TickFactor;

年で年齢を計算するキリスト教の方法では:

var then = ... // Then, in this case the birthday
var now = DateTime.UtcNow;
int age = now.Year - then.Year;
if (now.AddYears(-age) < then) age--;

財務では、日カウントの割合と呼ばれることが多いものを計算するときにも同様の問題が発生します。これは、特定の期間のおよその年数です。そして、年齢の問題は本当に時間測定の問題です。

実際/実際(すべての日を「正しく」数える)規則の例:

DateTime start, end = .... // Whatever, assume start is before end

double startYearContribution = 1 - (double) start.DayOfYear / (double) (DateTime.IsLeapYear(start.Year) ? 366 : 365);
double endYearContribution = (double)end.DayOfYear / (double)(DateTime.IsLeapYear(end.Year) ? 366 : 365);
double middleContribution = (double) (end.Year - start.Year - 1);

double DCF = startYearContribution + endYearContribution + middleContribution;

時間を測定するもう1つの一般的な方法は、一般に「シリアル化」することです(この日付の命名規則を指名した人物は、真剣に取り組んでいるはずです)。

DateTime start, end = .... // Whatever, assume start is before end
int days = (end - start).Days;

秒の相対論的年齢がこれまでの生活の中での地球の周りの太陽の周期の大まかな概算よりも有用になるまでにどれくらいの時間を費やす必要があるのか​​と思います:)つまり、期間に場所またはそれ自体が有効であることのモーションを表す関数:)


TickFactorとはですか?
隣接

@Protiguous Ticks per second。ティックを秒に正規化するために使用されます。
flindeberg

17

これが解決策です。

DateTime dateOfBirth = new DateTime(2000, 4, 18);
DateTime currentDate = DateTime.Now;

int ageInYears = 0;
int ageInMonths = 0;
int ageInDays = 0;

ageInDays = currentDate.Day - dateOfBirth.Day;
ageInMonths = currentDate.Month - dateOfBirth.Month;
ageInYears = currentDate.Year - dateOfBirth.Year;

if (ageInDays < 0)
{
    ageInDays += DateTime.DaysInMonth(currentDate.Year, currentDate.Month);
    ageInMonths = ageInMonths--;

    if (ageInMonths < 0)
    {
        ageInMonths += 12;
        ageInYears--;
    }
}

if (ageInMonths < 0)
{
    ageInMonths += 12;
    ageInYears--;
}

Console.WriteLine("{0}, {1}, {2}", ageInYears, ageInMonths, ageInDays);

文字列連結では、次のことが可能になります。47年11月7日
JoshYates1980

16

これは、2月28日の任意の年と比較して、2月29日の誕生日を解決できる最も正確な回答の1つです。

public int GetAge(DateTime birthDate)
{
    int age = DateTime.Now.Year - birthDate.Year;

    if (birthDate.DayOfYear > DateTime.Now.DayOfYear)
        age--;

    return age;
}




今日です!(次は今から4年後です。)
Peter Mortensen

15

私は年齢を計算するためのカスタマイズされた方法と、それが役立つ場合に備えてボーナス検証メッセージを持っています:

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
}

ここでメソッドを呼び出して日時値を渡します(サーバーがUSAロケールに設定されている場合は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

メッセージは好きなようにフォーマットできます。


14

このソリューションはどうですか?

static string CalcAge(DateTime birthDay)
{
    DateTime currentDate = DateTime.Now;         
    int approximateAge = currentDate.Year - birthDay.Year;
    int daysToNextBirthDay = (birthDay.Month * 30 + birthDay.Day) - 
        (currentDate.Month * 30 + currentDate.Day) ;

    if (approximateAge == 0 || approximateAge == 1)
    {                
        int month =  Math.Abs(daysToNextBirthDay / 30);
        int days = Math.Abs(daysToNextBirthDay % 30);

        if (month == 0)
            return "Your age is: " + daysToNextBirthDay + " days";

        return "Your age is: " + month + " months and " + days + " days"; ;
    }

    if (daysToNextBirthDay > 0)
        return "Your age is: " + --approximateAge + " Years";

    return "Your age is: " + approximateAge + " Years"; ;
}

12
private int GetAge(int _year, int _month, int _day
{
    DateTime yourBirthDate= new DateTime(_year, _month, _day);

    DateTime todaysDateTime = DateTime.Today;
    int noOfYears = todaysDateTime.Year - yourBirthDate.Year;

    if (DateTime.Now.Month < yourBirthDate.Month ||
        (DateTime.Now.Month == yourBirthDate.Month && DateTime.Now.Day < yourBirthDate.Day))
    {
        noOfYears--;
    }

    return  noOfYears;
}

10

次のアプローチ(から抽出 .NETクラスDateDiffの期間ライブラリでは、カルチャー情報のカレンダーを考慮しています。

// ----------------------------------------------------------------------
private static int YearDiff( DateTime date1, DateTime date2 )
{
  return YearDiff( date1, date2, DateTimeFormatInfo.CurrentInfo.Calendar );
} // YearDiff

// ----------------------------------------------------------------------
private static int YearDiff( DateTime date1, DateTime date2, Calendar calendar )
{
  if ( date1.Equals( date2 ) )
  {
    return 0;
  }

  int year1 = calendar.GetYear( date1 );
  int month1 = calendar.GetMonth( date1 );
  int year2 = calendar.GetYear( date2 );
  int month2 = calendar.GetMonth( date2 );

  // find the the day to compare
  int compareDay = date2.Day;
  int compareDaysPerMonth = calendar.GetDaysInMonth( year1, month1 );
  if ( compareDay > compareDaysPerMonth )
  {
    compareDay = compareDaysPerMonth;
  }

  // build the compare date
  DateTime compareDate = new DateTime( year1, month2, compareDay,
    date2.Hour, date2.Minute, date2.Second, date2.Millisecond );
  if ( date2 > date1 )
  {
    if ( compareDate < date1 )
    {
      compareDate = compareDate.AddYears( 1 );
    }
  }
  else
  {
    if ( compareDate > date1 )
    {
      compareDate = compareDate.AddYears( -1 );
    }
  }
  return year2 - calendar.GetYear( compareDate );
} // YearDiff

使用法:

// ----------------------------------------------------------------------
public void CalculateAgeSamples()
{
  PrintAge( new DateTime( 2000, 02, 29 ), new DateTime( 2009, 02, 28 ) );
  // > Birthdate=29.02.2000, Age at 28.02.2009 is 8 years
  PrintAge( new DateTime( 2000, 02, 29 ), new DateTime( 2012, 02, 28 ) );
  // > Birthdate=29.02.2000, Age at 28.02.2012 is 11 years
} // CalculateAgeSamples

// ----------------------------------------------------------------------
public void PrintAge( DateTime birthDate, DateTime moment )
{
  Console.WriteLine( "Birthdate={0:d}, Age at {1:d} is {2} years", birthDate, moment, YearDiff( birthDate, moment ) );
} // PrintAge

10

この古典的な質問は野田時間に値するソリューションに。

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パラメータもます。

このテーマに関する私のブログ投稿も参照してください:誕生日の処理、およびその他の記念日


あなたは野田タイムと提携していますか?
Zimano

私はそれに貢献しましたが、それは主にジョン・スキートのものです。
Matt Johnson-Pint

9

私はScArcher2のソリューションを使用して人の年齢の正確な年を計算しましたが、さらにそれを使用して、年とともに月と日を計算する必要がありました。

    public static Dictionary<string,int> CurrentAgeInYearsMonthsDays(DateTime? ndtBirthDate, DateTime? ndtReferralDate)
    {
        //----------------------------------------------------------------------
        // Can't determine age if we don't have a dates.
        //----------------------------------------------------------------------
        if (ndtBirthDate == null) return null;
        if (ndtReferralDate == null) return null;

        DateTime dtBirthDate = Convert.ToDateTime(ndtBirthDate);
        DateTime dtReferralDate = Convert.ToDateTime(ndtReferralDate);

        //----------------------------------------------------------------------
        // Create our Variables
        //----------------------------------------------------------------------
        Dictionary<string, int> dYMD = new Dictionary<string,int>();
        int iNowDate, iBirthDate, iYears, iMonths, iDays;
        string sDif = "";

        //----------------------------------------------------------------------
        // Store off current date/time and DOB into local variables
        //---------------------------------------------------------------------- 
        iNowDate = int.Parse(dtReferralDate.ToString("yyyyMMdd"));
        iBirthDate = int.Parse(dtBirthDate.ToString("yyyyMMdd"));

        //----------------------------------------------------------------------
        // Calculate Years
        //----------------------------------------------------------------------
        sDif = (iNowDate - iBirthDate).ToString();
        iYears = int.Parse(sDif.Substring(0, sDif.Length - 4));

        //----------------------------------------------------------------------
        // Store Years in Return Value
        //----------------------------------------------------------------------
        dYMD.Add("Years", iYears);

        //----------------------------------------------------------------------
        // Calculate Months
        //----------------------------------------------------------------------
        if (dtBirthDate.Month > dtReferralDate.Month)
            iMonths = 12 - dtBirthDate.Month + dtReferralDate.Month - 1;
        else
            iMonths = dtBirthDate.Month - dtReferralDate.Month;

        //----------------------------------------------------------------------
        // Store Months in Return Value
        //----------------------------------------------------------------------
        dYMD.Add("Months", iMonths);

        //----------------------------------------------------------------------
        // Calculate Remaining Days
        //----------------------------------------------------------------------
        if (dtBirthDate.Day > dtReferralDate.Day)
            //Logic: Figure out the days in month previous to the current month, or the admitted month.
            //       Subtract the birthday from the total days which will give us how many days the person has lived since their birthdate day the previous month.
            //       then take the referral date and simply add the number of days the person has lived this month.

            //If referral date is january, we need to go back to the following year's December to get the days in that month.
            if (dtReferralDate.Month == 1)
                iDays = DateTime.DaysInMonth(dtReferralDate.Year - 1, 12) - dtBirthDate.Day + dtReferralDate.Day;       
            else
                iDays = DateTime.DaysInMonth(dtReferralDate.Year, dtReferralDate.Month - 1) - dtBirthDate.Day + dtReferralDate.Day;       
        else
            iDays = dtReferralDate.Day - dtBirthDate.Day;             

        //----------------------------------------------------------------------
        // Store Days in Return Value
        //----------------------------------------------------------------------
        dYMD.Add("Days", iDays);

        return dYMD;
}

9

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  

8

Mark Soenの答えに小さな変更を1つ加えました。3番目の行を書き直して、式をもう少し簡単に解析できるようにしました。

public int AgeInYears(DateTime bday)
{
    DateTime now = DateTime.Today;
    int age = now.Year - bday.Year;            
    if (bday.AddYears(age) > now) 
        age--;
    return age;
}

また、わかりやすくするために関数にしています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.