Bei einer DateTime
Darstellung eines Geburtstag einer Person, wie berechne ich ihr Alter in Jahren?
Bei einer DateTime
Darstellung eines Geburtstag einer Person, wie berechne ich ihr Alter in Jahren?
Antworten:
Eine leicht verständliche und einfache Lösung.
// 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--;
Dies setzt jedoch voraus, dass Sie nach der westlichen Idee des Alters suchen und keine ostasiatische Abrechnung verwenden .
Dies ist eine seltsame Methode, aber wenn Sie das Datum so formatieren yyyymmdd
und das Geburtsdatum vom aktuellen Datum abziehen, lassen Sie die letzten 4 Ziffern fallen, für die Sie das Alter haben :)
Ich kenne C # nicht, aber ich glaube, dass dies in jeder Sprache funktionieren wird.
20080814 - 19800703 = 280111
Löschen Sie die letzten 4 Ziffern = 28
.
C # -Code:
int now = int.Parse(DateTime.Now.ToString("yyyyMMdd"));
int dob = int.Parse(dateOfBirth.ToString("yyyyMMdd"));
int age = (now - dob) / 10000;
Oder alternativ ohne die gesamte Typkonvertierung in Form einer Erweiterungsmethode. Fehlerprüfung weggelassen:
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
. Lassen Sie die letzten 4 Ziffern fallen und Sie haben (eine implizite) 0
für das Alter. Wie bist du gekommen 1
?
Hier ist ein Testausschnitt:
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
Hier haben Sie die Methoden:
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;
}
Die einfache Antwort darauf lautet AddYears
wie unten gezeigt, da dies die einzige native Methode ist, um Jahre zum 29. Februar der Schaltjahre hinzuzufügen und das korrekte Ergebnis des 28. Februar für gemeinsame Jahre zu erhalten.
Einige glauben, dass der 1. März der Geburtstag von Sprüngen ist, aber weder .Net noch eine offizielle Regel unterstützen dies, noch erklärt die allgemeine Logik, warum einige, die im Februar geboren wurden, 75% ihrer Geburtstage in einem anderen Monat haben sollten.
Ferner kann eine Altersmethode als Erweiterung hinzugefügt werden DateTime
. Auf diese Weise können Sie das Alter auf einfachste Weise ermitteln:
int age =irthDate.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;
}
}
Führen Sie nun diesen Test aus:
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();
}
}
Das Beispiel für ein kritisches Datum lautet:
Geburtsdatum: 2000-02-29 Späteres Datum: 2011-02-28 Alter: 11
Ausgabe:
{
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
}
Und für den späteren Zeitpunkt 28.02.2012:
{
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)
?
Mein Vorschlag
int age = (int) ((DateTime.Now - bday).TotalDays/365.242199);
Das Jahr scheint sich zum richtigen Zeitpunkt zu ändern. (Ich habe bis zum Alter von 107 Jahren vor Ort getestet.)
days in a year = 365.242199
Eine andere Funktion, nicht von mir, sondern im Web gefunden und ein wenig verfeinert:
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;
}
Nur zwei Dinge, die mir in den Sinn kommen: Was ist mit Menschen aus Ländern, die den Gregorianischen Kalender nicht verwenden? DateTime.Now gehört meiner Meinung nach zur serverspezifischen Kultur. Ich habe absolut keine Kenntnisse über die tatsächliche Arbeit mit asiatischen Kalendern und ich weiß nicht, ob es eine einfache Möglichkeit gibt, Daten zwischen Kalendern umzuwandeln, aber nur für den Fall, dass Sie sich über diese Chinesen aus dem Jahr 4660 wundern :-)
2 Hauptprobleme zu lösen sind:
1. Berechnen Sie das genaue Alter - in Jahren, Monaten, Tagen usw.
2. Allgemein wahrgenommenes Alter berechnen - Menschen kümmern sich normalerweise nicht darum, wie alt sie genau sind, sie kümmern sich nur darum, wann ihr Geburtstag im laufenden Jahr ist.
Lösung für 1 ist offensichtlich:
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
Die Lösung für 2 ist diejenige, die bei der Bestimmung des Gesamtalters nicht so genau ist, aber von Menschen als präzise wahrgenommen wird. Leute benutzen es normalerweise auch, wenn sie ihr Alter "manuell" berechnen:
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
}
Anmerkungen zu 2.:
Nur noch eine Anmerkung ... Ich würde 2 statische überladene Methoden dafür erstellen, eine für den universellen Gebrauch, die zweite für die Benutzerfreundlichkeit:
public static int GetAge(DateTime bithDay, DateTime today)
{
//chosen solution method body
}
public static int GetAge(DateTime birthDay)
{
return GetAge(birthDay, DateTime.Now);
}
Hier ist ein Einzeiler:
int age = new DateTime(DateTime.Now.Subtract(birthday).Ticks).Year-1;
Dies ist die Version, die wir hier verwenden. Es funktioniert und ist ziemlich einfach. Es ist die gleiche Idee wie bei Jeff, aber ich denke, es ist etwas klarer, weil es die Logik zum Subtrahieren einer trennt, so dass es etwas einfacher zu verstehen ist.
public static int GetAge(this DateTime dateOfBirth, DateTime dateAsAt)
{
return dateAsAt.Year - dateOfBirth.Year - (dateOfBirth.DayOfYear < dateAsAt.DayOfYear ? 0 : 1);
}
Sie können den ternären Operator erweitern, um ihn noch deutlicher zu machen, wenn Sie der Meinung sind, dass dies unklar ist.
Natürlich wird dies als Erweiterungsmethode ausgeführt DateTime
, aber Sie können natürlich die eine Codezeile, die die Arbeit erledigt, abrufen und überall platzieren. Hier haben wir eine weitere Überladung der Erweiterungsmethode, die der DateTime.Now
Vollständigkeit halber übergeben wird.
Der beste Weg, den ich aufgrund von Schaltjahren und allem kenne, ist:
DateTime birthDate = new DateTime(2000,3,1);
int age = (int)Math.Floor((DateTime.Now - birthDate).TotalDays / 365.25D);
Ich benutze das:
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;
}
}
Dies gibt "mehr Details" zu dieser Frage. Vielleicht ist es das, wonach Sie suchen
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);
Ich habe eine benutzerdefinierte SQL Server-Funktion erstellt, um das Alter einer Person anhand ihres Geburtsdatums zu berechnen. Dies ist nützlich, wenn Sie es als Teil einer Abfrage benötigen:
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;
}
};
Hier ist noch eine andere Antwort:
public static int AgeInYears(DateTime birthday, DateTime today)
{
return ((today.Year - birthday.Year) * 372 + (today.Month - birthday.Month) * 31 + (today.Day - birthday.Day)) / 372;
}
Dies wurde ausgiebig getestet. Es sieht ein bisschen "magisch" aus. Die Zahl 372 ist die Anzahl der Tage in einem Jahr, wenn jeder Monat 31 Tage hätte.
Die Erklärung, warum es funktioniert ( von hier aufgehoben ), ist:
Lass uns setzen
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
Wir wissen, dass wir entweder brauchen,
Yn-Yb
wenn das Datum bereits erreichtYn-Yb-1
ist, oder nicht.a) Wenn
Mn<Mb
ja-341 <= 31*(Mn-Mb) <= -31 and -30 <= Dn-Db <= 30
-371 <= 31*(Mn - Mb) + (Dn - Db) <= -1
Mit ganzzahliger Division
(31*(Mn - Mb) + (Dn - Db)) / 372 = -1
b) Wenn
Mn=Mb
undDn<Db
haben wir31*(Mn - Mb) = 0 and -30 <= Dn-Db <= -1
Wieder mit ganzzahliger Division
(31*(Mn - Mb) + (Dn - Db)) / 372 = -1
c) Wenn
Mn>Mb
ja31 <= 31*(Mn-Mb) <= 341 and -30 <= Dn-Db <= 30
1 <= 31*(Mn - Mb) + (Dn - Db) <= 371
Mit ganzzahliger Division
(31*(Mn - Mb) + (Dn - Db)) / 372 = 0
d) Wenn
Mn=Mb
undDn>Db
, haben wir31*(Mn - Mb) = 0 and 1 <= Dn-Db <= 3
0Wieder mit ganzzahliger Division
(31*(Mn - Mb) + (Dn - Db)) / 372 = 0
e) Wenn
Mn=Mb
undDn=Db
haben wir31*(Mn - Mb) + Dn-Db = 0
und deshalb
(31*(Mn - Mb) + (Dn - Db)) / 372 = 0
Ich habe einige Zeit damit verbracht, daran zu arbeiten, und mir das ausgedacht, um das Alter einer Person in Jahren, Monaten und Tagen zu berechnen. Ich habe gegen das Problem vom 29. Februar und die Schaltjahre getestet und es scheint zu funktionieren. Ich würde mich über jedes Feedback freuen:
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++;
}
}
Müssen wir Menschen berücksichtigen, die kleiner als 1 Jahr sind? Als chinesische Kultur beschreiben wir das Alter kleiner Babys als 2 Monate oder 4 Wochen.
Im Folgenden ist meine Implementierung aufgeführt. Es ist nicht so einfach, wie ich es mir vorgestellt habe, insbesondere, um mit einem Datum wie 2/28 umzugehen.
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";
}
}
Diese Implementierung wurde unter Testfällen bestanden.
[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);
}
Hoffe es ist hilfreich.
Halte es einfach (und möglicherweise dumm :)).
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.");
Der einfachste Weg, den ich je gefunden habe, ist dieser. Es funktioniert korrekt für die USA und Westeuropa. Ich kann nicht mit anderen Orten sprechen, besonders mit Orten wie China. 4 zusätzliche Vergleiche höchstens nach der anfänglichen Berechnung des Alters.
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 ;
}
Ich habe mir die Antworten darauf angesehen und festgestellt, dass niemand auf die regulatorischen / rechtlichen Auswirkungen von Schalttagsgeburten Bezug genommen hat. Wenn Sie beispielsweise laut Wikipedia am 29. Februar in verschiedenen Ländern geboren wurden, variiert der Geburtstag ohne Schaltjahr:
Und soweit ich das beurteilen kann, schweigen die Statuten in den USA zu diesem Thema und überlassen es dem Common Law und der Art und Weise, wie verschiedene Regulierungsbehörden die Dinge in ihren Vorschriften definieren.
Zu diesem Zweck eine Verbesserung:
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;
}
Es ist zu beachten, dass dieser Code Folgendes voraussetzt:
TimeSpan diff = DateTime.Now - birthdayDateTime;
string age = String.Format("{0:%y} years, {0:%M} months, {0:%d}, days old", diff);
Ich bin mir nicht sicher, wie genau es Ihnen zurückgegeben werden soll, also habe ich gerade eine lesbare Zeichenfolge erstellt.
Dies ist keine direkte Antwort, sondern eher eine philosophische Argumentation über das vorliegende Problem aus quasi-wissenschaftlicher Sicht.
Ich würde argumentieren, dass die Frage weder die Einheit noch die Kultur angibt, in der das Alter gemessen werden soll. Die meisten Antworten scheinen eine ganzzahlige jährliche Darstellung anzunehmen. Die SI-Einheit für die Zeit ist second
, daher sollte die richtige generische Antwort lauten (natürlich unter der Annahme einer Normalisierung DateTime
und ohne Berücksichtigung relativistischer Effekte):
var lifeInSeconds = (DateTime.Now.Ticks - then.Ticks)/TickFactor;
Auf christliche Weise zur Berechnung des Alters in Jahren:
var then = ... // Then, in this case the birthday
var now = DateTime.UtcNow;
int age = now.Year - then.Year;
if (now.AddYears(-age) < then) age--;
In der Finanzbranche gibt es ein ähnliches Problem bei der Berechnung von Daten, die häufig als Tageszählungsbruch bezeichnet werden und ungefähr eine Anzahl von Jahren für einen bestimmten Zeitraum umfassen. Und das Altersproblem ist wirklich ein Zeitmessproblem.
Beispiel für die Konvention Ist / Ist (Zählen aller Tage "richtig"):
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;
Eine andere übliche Methode, um die Zeit im Allgemeinen zu messen, ist das "Serialisieren" (der Typ, der diese Datumskonvention benannt hat, muss ernsthaft gestolpert sein):
DateTime start, end = .... // Whatever, assume start is before end
int days = (end - start).Days;
Ich frage mich, wie lange wir brauchen, bis ein relativistisches Zeitalter in Sekunden nützlicher wird als die grobe Annäherung der Erd-um-die-Sonne-Zyklen während des bisherigen Lebens :) Oder mit anderen Worten, wenn eine Periode einen Ort erhalten muss oder eine Funktion, die Bewegung für sich selbst darstellt, um gültig zu sein :)
Hier ist eine Lösung.
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);
Dies ist eine der genauesten Antworten, mit denen der Geburtstag vom 29. Februar im Vergleich zu jedem Jahr vom 28. Februar aufgelöst werden kann.
public int GetAge(DateTime birthDate)
{
int age = DateTime.Now.Year - birthDate.Year;
if (birthDate.DayOfYear > DateTime.Now.DayOfYear)
age--;
return age;
}
Ich habe eine angepasste Methode zur Berechnung des Alters sowie eine Bonusvalidierungsnachricht für den Fall, dass dies hilfreich ist:
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
}
Methodenaufruf hier und Ausgabe des Datums- / Uhrzeitwerts (MM / TT / JJJJ, wenn der Server auf das Gebietsschema USA eingestellt ist). Ersetzen Sie dies durch eine Nachrichtbox oder einen Container, der angezeigt werden soll:
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
Denken Sie daran, dass Sie die Nachricht beliebig formatieren können.
Wie wäre es mit dieser Lösung?
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;
}
Der folgende Ansatz (Auszug aus der Zeitperiodenbibliothek für die .NET- Klasse DateDiff ) berücksichtigt den Kalender der Kulturinformationen:
// ----------------------------------------------------------------------
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
Verwendungszweck:
// ----------------------------------------------------------------------
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
Diese klassische Frage verdient eine Noda Time- Lösung.
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;
}
Verwendungszweck:
LocalDate dateOfBirth = new LocalDate(1976, 8, 27);
int age = GetAge(dateOfBirth);
Sie könnten auch an folgenden Verbesserungen interessiert sein:
Das Eingeben der Uhr als IClock
anstelle der Verwendung SystemClock.Instance
würde die Testbarkeit verbessern.
Die Zielzeitzone wird sich wahrscheinlich ändern, daher möchten Sie auch einen DateTimeZone
Parameter.
Siehe auch meinen Blog-Beitrag zu diesem Thema: Umgang mit Geburtstagen und anderen Jubiläen
Ich habe die Lösung von ScArcher2 für eine genaue Jahresberechnung des Alters einer Person verwendet, musste sie jedoch weiterentwickeln und ihre Monate und Tage zusammen mit den Jahren berechnen.
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;
}
Ich habe eine kleine Änderung an Mark Soens Antwort vorgenommen: Ich habe die dritte Zeile neu geschrieben, damit der Ausdruck etwas einfacher analysiert werden kann.
public int AgeInYears(DateTime bday)
{
DateTime now = DateTime.Today;
int age = now.Year - bday.Year;
if (bday.AddYears(age) > now)
age--;
return age;
}
Ich habe es aus Gründen der Klarheit auch zu einer Funktion gemacht.