c# - yyyymmddhhmmss datetime
C#で誰かの年齢を計算するにはどうすればよいですか? (20)
ある人の誕生日を表す
DateTime
与えられた場合、どのように年数を計算しますか?
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
この古典的な質問は、 Noda Time ソリューションに 値するものです 。
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
パラメータも必要です。
このテーマに関する私のブログ投稿も参照してください。 誕生日の取り扱い、およびその他の記念日
これが解決策です。
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);
これは、2月29日の誕生日を2月28日の任意の年と比較して解決できる最も正確な答えの1つです。
public int GetAge(DateTime birthDate)
{
int age = DateTime.Now.Year - birthDate.Year;
if (birthDate.DayOfYear > DateTime.Now.DayOfYear)
age--;
return age;
}
次のアプローチ( .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
私が今まで見つけた最も簡単な方法はこれです。 米国および西ヨーロッパのロケールでは正しく機能します。 他のロケール、特に中国のような場所とは話すことができません。 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 ;
}
私はこれに対する答えを見ていました、そしてうるう日の出産の規制/法的な含意について誰も言及しなかったことに気づきました。 たとえば、 ウィキペディアによると 、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つ挿入するグレゴリオ暦のようなカレンダー。
私は年齢を計算するためのカスタマイズされた方法と、それが役に立つ場合に備えてボーナス確認メッセージを持っています:
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
}
ここでメソッドを呼び出して日時値を渡します(サーバーがアメリカのロケールに設定されている場合は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
あなたが好きなようにメッセージをフォーマットすることができることを忘れないでください。
2解決すべき主な問題は以下のとおりです。
1.正確な年齢を計算します - 年、月、日などで。
一般的に認識されている年齢を計算する - 人々は通常彼らが正確に何歳であるかを気にしない、彼らは今年の彼らの誕生日がいつであるかを気にする。
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);
}
これに対する簡単な答えは、以下に示すように
AddYears
を適用することです。これは、うるう年の2月29日に年を追加し、一般的な年の2月28日の正しい結果を取得する唯一のネイティブメソッドだからです。
3月1日が跳躍の誕生日だと思う人もいますが、.Netも公式の規則もこれを支持しておらず、2月に生まれた人の誕生日の75%が別の月になるのはなぜなのかという説明もありません。
さらに、Ageメソッドは
DateTime
拡張として追加するのに適しています。
これにより、最も簡単な方法で年齢を取得できます。
- リスト項目
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
}
これはまた別の答えです。
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=Mb
かつDn<Db
場合、31*(Mn - Mb) = 0 and -30 <= Dn-Db <= -1
整数除算を使って
(31*(Mn - Mb) + (Dn - Db)) / 372 = -1
c)
Mn>Mb
場合、31 <= 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=Mb
かつDn>Db
場合、31*(Mn - Mb) = 0 and 1 <= Dn-Db <= 3
0となる。整数除算を使って
(31*(Mn - Mb) + (Dn - Db)) / 372 = 0
e)
Mn=Mb
かつDn=Db
場合、31*(Mn - Mb) + Dn-Db = 0
したがって、
(31*(Mn - Mb) + (Dn - Db)) / 372 = 0
これは私たちがここで使っているバージョンです。 それはうまくいきます、そしてそれはかなり単純です。 これはJeffと同じアイデアですが、1を引くためのロジックを分離しているので、もう少し明確になっていると思います。
public static int GetAge(this DateTime dateOfBirth, DateTime dateAsAt)
{
return dateAsAt.Year - dateOfBirth.Year - (dateOfBirth.DayOfYear < dateAsAt.DayOfYear ? 0 : 1);
}
そのようなことがはっきりしないと思うならば、あなたはそれをさらに明確にするために三項演算子を拡張することができます。
明らかにこれは
DateTime
拡張メソッドとして行われますが、明らかにあなたはその仕事をする1行のコードをつかみ、それをどこにでも置くことができます。
ここでは、完全を
DateTime.Now
ために、
DateTime.Now
を渡すExtensionメソッドの別のオーバーロードがあります。
それを単純にしておく(そしておそらくばかげている:))。
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.");
わかりやすく簡単な解決策。
// 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--;
しかし、これはあなたが 西洋 の年齢の考えを探していて 東アジアの計算 を使わないことを前提としています。
私がうるう年とすべてのことを知っている最善の方法は、次のとおりです。
DateTime birthDate = new DateTime(2000,3,1);
int age = (int)Math.Floor((DateTime.Now - birthDate).TotalDays / 365.25D);
お役に立てれば。
私のおすすめ
int age = (int) ((DateTime.Now - bday).TotalDays/365.242199);
それは年が正しい日に変わっているようです。 (私は107歳までのスポットテスト)
私は、誕生日を考えて、誰かの年齢を計算するための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;
}
};
私はこれを使う:
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;
}
}
私はパーティーに遅刻しました、しかしここにワンライナーがあります:
int age = new DateTime(DateTime.Now.Subtract(birthday).Ticks).Year-1;
間違った解決策がどのように受け入れられるのか私は知りません。 正しいC#スニペットは、Michael Stumによって書かれました。
これがテストスニペットです。
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;
}
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;
}