Diberikan DateTime
mewakili ulang tahun seseorang, bagaimana cara menghitung usia mereka dalam tahun?
Diberikan DateTime
mewakili ulang tahun seseorang, bagaimana cara menghitung usia mereka dalam tahun?
Jawaban:
Solusi yang mudah dimengerti dan sederhana.
// 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--;
Namun, ini mengasumsikan Anda mencari ide barat usia dan tidak menggunakan perhitungan Asia Timur .
Ini adalah cara yang aneh untuk melakukannya, tetapi jika Anda memformat tanggal yyyymmdd
dan mengurangi tanggal lahir dari tanggal saat ini maka turunkan 4 digit terakhir Anda sudah mendapatkan usia :)
Saya tidak tahu C #, tetapi saya yakin ini akan berhasil dalam bahasa apa pun.
20080814 - 19800703 = 280111
Jatuhkan 4 digit terakhir = 28
.
Kode C #:
int now = int.Parse(DateTime.Now.ToString("yyyyMMdd"));
int dob = int.Parse(dateOfBirth.ToString("yyyyMMdd"));
int age = (now - dob) / 10000;
Atau sebagai alternatif tanpa semua konversi jenis dalam bentuk metode ekstensi. Pemeriksaan kesalahan dihilangkan:
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;
}
20180101 - 20171231 = 8870
. Jatuhkan 4 digit terakhir dan Anda memiliki (tersirat) 0
untuk usia tersebut. Bagaimana kau bisa 1
?
Berikut ini cuplikan uji:
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
Di sini Anda memiliki metode:
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;
}
Jawaban sederhana untuk ini adalah untuk menerapkan AddYears
seperti yang ditunjukkan di bawah ini karena ini adalah satu-satunya metode asli untuk menambahkan tahun ke 29 Februari tahun kabisat dan mendapatkan hasil yang benar dari 28 Februari untuk tahun-tahun umum.
Beberapa merasa bahwa 1 Maret adalah hari ulang tahun lompatan tetapi Net. Maupun aturan resmi tidak mendukung ini, logika umum juga tidak menjelaskan mengapa beberapa orang yang lahir di bulan Februari seharusnya memiliki 75% ulang tahun mereka di bulan lain.
Selanjutnya, metode Usia cocok untuk ditambahkan sebagai ekstensi untuk DateTime
. Dengan ini, Anda dapat memperoleh usia dengan cara sesederhana mungkin:
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;
}
}
Sekarang, jalankan tes ini:
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();
}
}
Contoh tanggal kritis adalah ini:
Tanggal lahir: 2000-02-29 Tanggal kemudian: 2011-02-28 Usia: 11
Keluaran:
{
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
}
Dan untuk tanggal selanjutnya 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
}
date.Age(other)
?
Saran saya
int age = (int) ((DateTime.Now - bday).TotalDays/365.242199);
Tampaknya tahun berubah pada tanggal yang tepat. (Saya dites hingga usia 107 tahun.)
days in a year = 365.242199
Fungsi lain, bukan oleh saya tetapi ditemukan di web dan sedikit disempurnakan:
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;
}
Hanya dua hal yang muncul di benak saya: Bagaimana dengan orang-orang dari negara yang tidak menggunakan kalender Gregorian? DateTime.Now dalam budaya spesifik server saya pikir. Saya benar-benar tidak memiliki pengetahuan tentang benar-benar bekerja dengan kalender Asia dan saya tidak tahu apakah ada cara mudah untuk mengubah tanggal antara kalender, tetapi kalau-kalau Anda bertanya-tanya tentang orang-orang Cina dari tahun 4660 :-)
2 masalah utama yang harus dipecahkan adalah:
1. Hitung usia Persis - dalam tahun, bulan, hari, dll.
2. Menghitung Umur yang dirasakan secara umum - orang biasanya tidak peduli berapa usia mereka sebenarnya, mereka hanya peduli ketika ulang tahun mereka pada tahun berjalan.
Solusi untuk 1 sudah jelas:
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
Solusi untuk 2 adalah solusi yang tidak terlalu tepat dalam menentukan usia total, tetapi dianggap tepat oleh orang-orang. Orang-orang juga biasanya menggunakannya, ketika mereka menghitung usia mereka "secara manual":
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
}
Catatan untuk 2 .:
Hanya satu catatan lagi ... Saya akan membuat 2 metode statis kelebihan beban untuk itu, satu untuk penggunaan universal, kedua untuk ramah penggunaan:
public static int GetAge(DateTime bithDay, DateTime today)
{
//chosen solution method body
}
public static int GetAge(DateTime birthDay)
{
return GetAge(birthDay, DateTime.Now);
}
Inilah satu kalimat:
int age = new DateTime(DateTime.Now.Subtract(birthday).Ticks).Year-1;
Ini adalah versi yang kami gunakan di sini. Ini bekerja, dan itu cukup sederhana. Itu ide yang sama dengan Jeff tetapi saya pikir ini sedikit lebih jelas karena memisahkan logika untuk mengurangi satu, jadi itu sedikit lebih mudah untuk dipahami.
public static int GetAge(this DateTime dateOfBirth, DateTime dateAsAt)
{
return dateAsAt.Year - dateOfBirth.Year - (dateOfBirth.DayOfYear < dateAsAt.DayOfYear ? 0 : 1);
}
Anda dapat memperluas operator ternary untuk membuatnya lebih jelas, jika Anda berpikir hal semacam itu tidak jelas.
Jelas ini dilakukan sebagai metode ekstensi DateTime
, tetapi jelas Anda dapat mengambil satu baris kode yang berfungsi dan meletakkannya di mana saja. Di sini kita memiliki kelebihan lain dari metode Extension yang masuk DateTime.Now
, hanya untuk kelengkapan.
Cara terbaik yang saya tahu karena tahun kabisat dan semuanya adalah:
DateTime birthDate = new DateTime(2000,3,1);
int age = (int)Math.Floor((DateTime.Now - birthDate).TotalDays / 365.25D);
Saya menggunakan ini:
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;
}
}
Ini memberikan "lebih detail" untuk pertanyaan ini. Mungkin ini yang Anda cari
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);
Saya telah membuat Fungsi Ditentukan Pengguna SQL Server untuk menghitung usia seseorang, mengingat tanggal lahirnya. Ini berguna ketika Anda membutuhkannya sebagai bagian dari permintaan:
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;
}
};
Ini jawaban lain:
public static int AgeInYears(DateTime birthday, DateTime today)
{
return ((today.Year - birthday.Year) * 372 + (today.Month - birthday.Month) * 31 + (today.Day - birthday.Day)) / 372;
}
Ini telah diuji unit secara ekstensif. Itu memang terlihat sedikit "ajaib". Angka 372 adalah jumlah hari dalam satu tahun jika setiap bulan memiliki 31 hari.
Penjelasan mengapa ia bekerja ( diangkat dari sini ) adalah:
Mari kita atur
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
Kita tahu bahwa yang kita butuhkan adalah
Yn-Yb
apakah tanggal telah tercapai,Yn-Yb-1
jika belum.a) Jika
Mn<Mb
, kita punya-341 <= 31*(Mn-Mb) <= -31 and -30 <= Dn-Db <= 30
-371 <= 31*(Mn - Mb) + (Dn - Db) <= -1
Dengan divisi integer
(31*(Mn - Mb) + (Dn - Db)) / 372 = -1
b) Jika
Mn=Mb
danDn<Db
, kita punya31*(Mn - Mb) = 0 and -30 <= Dn-Db <= -1
Dengan pembagian integer, lagi
(31*(Mn - Mb) + (Dn - Db)) / 372 = -1
c) Jika
Mn>Mb
, kita punya31 <= 31*(Mn-Mb) <= 341 and -30 <= Dn-Db <= 30
1 <= 31*(Mn - Mb) + (Dn - Db) <= 371
Dengan divisi integer
(31*(Mn - Mb) + (Dn - Db)) / 372 = 0
d) Jika
Mn=Mb
danDn>Db
, kita memiliki31*(Mn - Mb) = 0 and 1 <= Dn-Db <= 3
0Dengan pembagian integer, lagi
(31*(Mn - Mb) + (Dn - Db)) / 372 = 0
e) Jika
Mn=Mb
danDn=Db
, kami punya31*(Mn - Mb) + Dn-Db = 0
dan oleh karena itu
(31*(Mn - Mb) + (Dn - Db)) / 372 = 0
Saya telah menghabiskan beberapa waktu mengerjakan ini dan menghasilkan ini untuk menghitung usia seseorang dalam tahun, bulan, dan hari. Saya telah menguji terhadap masalah 29 Februari dan tahun kabisat dan tampaknya berhasil, saya menghargai umpan balik:
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++;
}
}
Apakah kita perlu mempertimbangkan orang yang lebih kecil dari 1 tahun? sebagai budaya Cina, kami menggambarkan usia bayi kecil sebagai 2 bulan atau 4 minggu.
Di bawah ini adalah implementasi saya, tidak sesederhana yang saya bayangkan, terutama untuk berurusan dengan tanggal seperti 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";
}
}
Implementasi ini telah melewati uji kasus di bawah ini.
[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);
}
Semoga bermanfaat.
Tetap sederhana (dan mungkin bodoh :)).
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.");
Cara paling sederhana yang pernah saya temukan adalah ini. Ini bekerja dengan benar untuk lokal AS dan Eropa Barat. Tidak dapat berbicara dengan lokal lain, terutama tempat-tempat seperti Cina. 4 perbandingan ekstra, paling banyak, mengikuti perhitungan awal usia.
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 ;
}
Saya mencari jawaban untuk ini dan memperhatikan bahwa tidak ada yang membuat referensi untuk implikasi peraturan / hukum kelahiran hari kabisat. Misalnya, per Wikipedia , jika Anda lahir pada tanggal 29 Februari di berbagai yurisdiksi, ulang tahun Anda bukan tahun kabisat bervariasi:
Dan sedekat yang dapat saya katakan, di AS, undang-undang tersebut diam mengenai masalah ini, menyerahkannya kepada hukum umum dan bagaimana berbagai badan pengawas mendefinisikan hal-hal dalam peraturan mereka.
Untuk itu, peningkatan:
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;
}
Perlu dicatat bahwa kode ini mengasumsikan:
TimeSpan diff = DateTime.Now - birthdayDateTime;
string age = String.Format("{0:%y} years, {0:%M} months, {0:%d}, days old", diff);
Saya tidak yakin bagaimana tepatnya Anda ingin mengembalikannya kepada Anda, jadi saya hanya membuat string yang dapat dibaca.
Ini bukan jawaban langsung, tetapi lebih merupakan alasan filosofis tentang masalah yang dihadapi dari sudut pandang semi-ilmiah.
Saya berpendapat bahwa pertanyaannya tidak menentukan satuan atau budaya di mana untuk mengukur usia, sebagian besar jawaban tampaknya menganggap representasi tahunan bilangan bulat. Satuan SI untuk waktu adalah second
, ergo jawaban generik yang benar harus (tentu saja dengan asumsi dinormalisasi DateTime
dan tidak memperhatikan efek relativistik):
var lifeInSeconds = (DateTime.Now.Ticks - then.Ticks)/TickFactor;
Dalam cara orang Kristen menghitung usia dalam tahun:
var then = ... // Then, in this case the birthday
var now = DateTime.UtcNow;
int age = now.Year - then.Year;
if (now.AddYears(-age) < then) age--;
Di bidang keuangan ada masalah yang sama ketika menghitung sesuatu yang sering disebut sebagai Fraksi Hitung Hari , yang kira-kira adalah beberapa tahun untuk periode tertentu. Dan masalah usia adalah masalah pengukuran waktu.
Contoh untuk konvensi aktual / aktual (menghitung semua hari "dengan benar"):
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;
Cara lain yang cukup umum untuk mengukur waktu secara umum adalah dengan "membuat cerita bersambung" (pria yang menamakan konvensi tanggal ini pasti serius '):
DateTime start, end = .... // Whatever, assume start is before end
int days = (end - start).Days;
Saya bertanya-tanya berapa lama kita harus pergi sebelum usia relativistik dalam hitungan detik menjadi lebih berguna daripada perkiraan kasar siklus bumi-sekitar-matahari selama hidup kita sejauh ini :) Atau dengan kata lain, ketika suatu periode harus diberi lokasi atau sebuah fungsi yang mewakili gerak untuk dirinya sendiri menjadi valid :)
Ini solusinya.
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);
Ini adalah salah satu jawaban yang paling akurat yang dapat menyelesaikan ulang tahun tanggal 29 Februari dibandingkan dengan tahun apa saja pada tanggal 28 Februari.
public int GetAge(DateTime birthDate)
{
int age = DateTime.Now.Year - birthDate.Year;
if (birthDate.DayOfYear > DateTime.Now.DayOfYear)
age--;
return age;
}
Saya memiliki metode khusus untuk menghitung usia, ditambah pesan validasi bonus untuk berjaga-jaga jika itu membantu:
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
}
Metode memanggil di sini dan membagikan nilai datetime (MM / hh / tttt jika server diatur ke lokal USA). Ganti ini dengan apa pun kotak pesan atau wadah apa pun untuk ditampilkan:
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
Ingat Anda dapat memformat pesan dengan cara apa pun yang Anda suka.
Bagaimana dengan solusi ini?
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"; ;
}
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;
}
Pendekatan berikut (ekstrak dari Perpustakaan Periode Waktu untuk .NET class DateDiff ) mempertimbangkan kalender info budaya:
// ----------------------------------------------------------------------
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
Pemakaian:
// ----------------------------------------------------------------------
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
Pertanyaan klasik ini layak mendapatkan solusi 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;
}
Pemakaian:
LocalDate dateOfBirth = new LocalDate(1976, 8, 27);
int age = GetAge(dateOfBirth);
Anda mungkin juga tertarik dengan peningkatan berikut:
Melewati jam sebagai IClock
, alih-alih menggunakan SystemClock.Instance
, akan meningkatkan kemampuan uji.
Zona waktu target kemungkinan akan berubah, jadi Anda juga menginginkan DateTimeZone
parameter.
Lihat juga posting blog saya tentang hal ini: Menangani Ulang Tahun, dan Peringatan Lainnya
Saya menggunakan solusi ScArcher2 untuk perhitungan Tahun yang akurat dari usia orang, tetapi saya perlu mengambilnya lebih jauh dan menghitung Bulan dan Hari mereka bersama dengan Tahun.
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;
}
Saya telah membuat satu perubahan kecil pada jawaban Mark Soen : Saya telah menulis ulang baris ketiga sehingga ekspresi dapat diurai sedikit lebih mudah.
public int AgeInYears(DateTime bday)
{
DateTime now = DateTime.Today;
int age = now.Year - bday.Year;
if (bday.AddYears(age) > now)
age--;
return age;
}
Saya juga membuatnya menjadi fungsi demi kejelasan.