Wie berechne ich in C # das Alter einer Person basierend auf einem DateTime-Geburtstag?

1867

Bei einer DateTimeDarstellung eines Geburtstag einer Person, wie berechne ich ihr Alter in Jahren?

Shaik Raffi
quelle
147
Was bisher alle Antworten übersehen haben, ist, dass es darauf ankommt, wo die Person geboren wurde und wo sie sich gerade befindet.
Yaur
40
@Yaur: Konvertieren Sie einfach die Zeit von jetzt + Geburt in GMT / UTC. Das Alter ist nur ein relativer Wert, daher sind Zeitzonen irrelevant. Zum Ermitteln der aktuellen Zeitzone des Benutzers können Sie GeoLocating verwenden.
Stefan Steiger
Warum nicht [Julian Date] [1] in Betracht ziehen? [1]: stackoverflow.com/questions/7103064/…
Muhammad Hewedy
5
Sollte die Sommerzeit die Berechnung in irgendeiner Weise beeinflussen, wenn wir @Yaurs Vorschlag für zeitzonenübergreifende Berechnungen berücksichtigen?
DDM
6
Abgestimmt, da dies eindeutig eine Hausaufgabenfrage ist und kein bestehender Versuch unternommen wurde.
Marie

Antworten:

2122

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 .

Mike Polen
quelle
252
Ich wollte nur die Leistung von DateTime.Now kommentieren. Wenn Sie keinen genauen Zeitzonenwert benötigen, verwenden Sie DateTime.UtcNow ist es viel schneller.
JAG
104
Da es sich um Geburtstage handelt, können Sie einfach DateTime verwenden. Heute hat der Zeitteil keine Relevanz.
Tristan Warner-Smith
78
Diese Antwort funktioniert nicht mit allen Gebietsschemas und allen Altersgruppen. Mehrere Länder haben Daten nach der Geburt der derzeit lebenden Menschen übersprungen, darunter Russland (1918), Griechenland (1924) und die Türkei (1926).
Lars D
30
Eigentlich ist es immer noch nicht ganz richtig. Dieser Code setzt voraus, dass 'bday' der Datumsteil einer DateTime ist. Es ist ein Randfall (ich denke, die meisten Leute werden nur Daten und keine Datums- und Uhrzeitangaben übergeben), aber wenn Sie einen Geburtstag als Datum und Uhrzeit übergeben, bei der die Zeit größer als 00:00:00 ist, dann sind Sie ' Ich werde auf den Fehler stoßen, auf den Danvil hingewiesen hat. Das Setzen von bday = bday.Date behebt dies.
Øyvind
119
Die letzte Zeile ließ mich zu viel nachdenken. Wie wäre es stattdessen mit: if (bday.AddYears (age)> now) age--; Dies scheint ein intuitiverer Ausdruck zu sein.
Cdiggins
1015

Dies ist eine seltsame Methode, aber wenn Sie das Datum so formatieren yyyymmddund 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;
}
ScArcher2
quelle
5
Eigentlich ist dies großartig für die Verwendung in MS-SQL mit Datetime-Feldern (Gesamttage seit 01-011900)
Patrik
5
@numerek Bitte posten Sie Ihre Änderungsvorschläge als eigene Antwort. Für das, was es wert ist, ist das aktuelle Jahr mal 10000 bei weitem kein annähernder ganzzahliger Überlauf um zwei Größenordnungen. 20.150.000 vs 2.147.483.648
GalacticCowboy
7
@ LongChalk 20180101 - 20171231 = 8870. Lassen Sie die letzten 4 Ziffern fallen und Sie haben (eine implizite) 0für das Alter. Wie bist du gekommen 1?
Rufus L
4
Ich weiß, dass dies eine alte Antwort ist, aber ich würde keine Erweiterungsmethode daraus machen. Es ist nicht der richtige Ort, um solche Logiken zu definieren.
Lucca Ferri
1
Was ist das für eine Zauberei?
Muleskinner
391

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;
}
RMA
quelle
33
Während dieser Code funktioniert, wird behauptet, dass eine Person, die an einem Schalttag geboren wurde, das nächste Jahr am 1. März in Nicht-Schaltjahren und nicht am 28. Februar erreicht. In der Realität kann jede Option richtig sein . Wikipedia hat dazu etwas zu sagen . Ihr Code ist also nicht "falsch", aber auch nicht die akzeptierte Lösung.
Matt Johnson-Pint
18
@ MattJohnson Ich denke das ist eigentlich richtig. Wenn mein Geburtstag der 29. Februar war, dann ist mein Geburtstag der 28. Februar nicht vergangen, und ich sollte immer noch das gleiche Alter wie am 27. Februar haben. Am 1. März haben wir jedoch meinen Geburtstag überschritten und ich sollte das nächste Alter sein. In den USA hat ein Unternehmen, das Alkohol verkauft, ein Schild mit der Aufschrift "Wenn Sie nach diesem Tag in JJJJ geboren wurden, können Sie keinen Alkohol kaufen" (wobei sich JJJJ jedes Jahr ändert). Das bedeutet, dass jemand, der am 29. Februar geboren wurde, am 28. Februar in dem Jahr, in dem er 21 wird (die meisten Orte), keinen Alkohol kaufen kann, und unterstützt die Idee, dass er erst am 1. März ein Jahr älter ist.
jfren484
4
@ jfren484 - lies den Wikipedia-Artikel. Es variiert erheblich zwischen den Gerichtsbarkeiten.
Matt Johnson-Pint
9
@ jfren484 Dein Anspruch hat absolut nichts mit Philosophie zu tun; aber alles was mit deinem persönlichen Gefühl zu tun hat . Wenn eine am 29. Februar geborene Person "Alter" ist weitgehend unwichtig, es sei denn, das Alter bildet eine "gesetzliche Altersgrenze" (z. B. Kann Alkohol kaufen, wählen, Rente erhalten, in die Armee eintreten, Führerschein erhalten). Betrachten Sie das Trinkalter in den USA (21 Jahre): Für die meisten Menschen sind das 7670 Tage. Es sind 7671 Tage, wenn sie vor dem 29. Februar im Schaltjahr oder ab dem 1. März vor dem Schaltjahr geboren wurden. Wenn am 29. Februar geboren: 28. Februar ist 7670 Tage und 1. März ist 7671 Tage. Die Wahl ist willkürlich und kann in beide Richtungen gehen.
Desillusioniert
4
@CraigYoung Du verstehst nicht, was ich mit philosophisch gemeint habe. Ich habe diesen Begriff als Kontrast zu legal verwendet. Wenn jemand einen Antrag schreibt, der das gesetzliche Alter einer Person kennen muss, muss er nur wissen, wie die Rechtsprechung, in der sein Antrag verwendet wird, zur Behandlung von Personen verwendet wird, die am 29. Februar geboren wurden. Wenn wir es jedoch sind darüber reden , wie das sollte behandelt werden, dann ist das per Definition Philosophie. Und ja, die Meinung, die ich abgegeben habe, ist meine eigene Meinung, aber wie gesagt, ich denke, es wäre einfacher, für den 1. März zu argumentieren als für den 28. Februar.
jfren484
110

Die einfache Antwort darauf lautet AddYearswie 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:

  1. Listenpunkt

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
}
camelCasus
quelle
4
Ein Kommentar zum 29. Februar-Geburtstag am 1. März ist technisch gesehen zu früh (tatsächlich 1 Tag früher). Am 1. ist ein Tag zu spät. Aber da der Geburtstag dazwischen liegt, ist es für mich sinnvoller, den 1. zu verwenden, um das Alter in Nicht-Schaltjahren zu berechnen, da diese Person zwar jedes Jahr am 1. März (und 2. und 3. März) so alt ist, aber nicht am 28. Februar.
CyberClaw
1
Unter dem Gesichtspunkt des Software-Designs macht es für mich wenig Sinn, dies als Erweiterungsmethode zu schreiben. date.Age(other)?
Marsze
90

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.)

James Curran
quelle
26
Ich glaube nicht, dass Harry Patch Ihre Spot-Test-Methode geschätzt hätte: latimes.com/news/obituaries/…
MusiGenesis
3
Google sagtdays in a year = 365.242199
mpen
12
Die durchschnittliche Länge eines Jahres im Gregorianischen Kalender beträgt 365,2425 Tage.
dan04
4
Ich würde sagen, dies ist eine der einfachsten Lösungen und es ist gut genug . Wen kümmert es, wenn ich einen halben Tag vor meinem X. Geburtstag bin und das Programm besagt, dass ich X Jahre alt bin. Das Programm ist mehr oder weniger richtig, wenn auch nicht mathematisch. Diese Lösung gefällt mir sehr gut.
Peter Perháč
13
^^ Weil es manchmal wichtig ist. In meinen Tests schlägt dies am Geburtstag der Person fehl, es meldet sie jünger als sie sind.
ChadT
76

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 :-)

Michael Stum
quelle
Dies scheint verschiedene Regionen (Datumsformate) am besten zu handhaben.
Webdad3
53

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.:

  • Dies ist meine bevorzugte Lösung
  • Wir können DateTime.DayOfYear oder TimeSpans nicht verwenden, da sie die Anzahl der Tage in Schaltjahren verschieben
  • Ich habe dort etwas mehr Zeilen für die Lesbarkeit gesetzt

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);
}
Thetam
quelle
50

Hier ist ein Einzeiler:

int age = new DateTime(DateTime.Now.Subtract(birthday).Ticks).Year-1;
SillyMonkey
quelle
23
Das ist kaputt. Testbar gemacht: public static int CalculateAge (DateTime dateOfBirth, DateTime dateToCalculateAge) {neue DateTime zurückgeben (dateToCalculateAge.Subtract (dateOfBirth) .Ticks) .Year - 1; } ... Gibt das 14. Lebensjahr an, wenn ich den 01.06.1990 eingebe und das Alter am Tag vor seinem 14. Geburtstag (31.05.1990) berechne.
Kjensen
43

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.NowVollständigkeit halber übergeben wird.

David Wengier
quelle
6
Ich denke, dies kann um einen Tag verschoben sein, wenn genau eines von Geburtsdatum oder Datumsangabe in ein Schaltjahr fällt. Berücksichtigen Sie das Alter einer Person, die am 1. März 2003 am 29. Februar 2004 geboren wurde. Um dies zu korrigieren, müssen Sie einen lexikografischen Vergleich von (Month, DayOfMonth) -Paaren durchführen und dieses für die Bedingung verwenden.
Doug McClean
1
Es wird auch nicht das richtige Alter ab Ihrem Geburtstag anzeigen.
Dotjoe
43

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);
Nick Berardi
quelle
34

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;
    }
}
Elmer
quelle
32

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);
Jacqueline Loriault
quelle
1
Dies funktioniert nicht immer. Das Hinzufügen eines Bereichs zu DateTime.MinValue könnte funktionieren. Dies berücksichtigt keine Schaltjahre usw. Wenn Sie die Jahre, Monate und Tage mit der Funktion AddYears (), AddMonths und AddDays () zum Alter hinzufügen, wird die Datetime nicht immer zurückgegeben Jetzt Datum.
Athanasios Kataras
3
Die Zeitspanne selbst berücksichtigt automatisch Schaltjahre zwischen zwei Daten, daher bin ich mir nicht sicher, was Sie vorhaben. Ich habe in Microsoft-Foren nachgefragt und Microsoft hat bestätigt, dass Schaltjahre zwischen zwei Daten berücksichtigt werden.
Jacqueline Loriault
2
Betrachten Sie die folgenden ZWEI Szenarien. 1st DateTime.Now ist der 1.1.2001 und ein Kind wird am 1.1.2000 geboren. 2000 ist ein Schaltjahr und das Ergebnis wird 1 Jahr, 0 Monate und 1 Tage sein. Im zweiten Senarion ist DateTime.Now der 1.1.2002 und das Kind wird am 1.1.2001 geboren. In diesem Fall beträgt das Ergebnis 1 Jahr, 0 Monate und 0 Tage. Dies geschieht, weil Sie die Zeitspanne für ein Jahr ohne Schaltzug hinzufügen. Wenn DateTime.MinValue ein Schaltjahr wäre, wären die Ergebnisse 1 Jahr im ersten und 0 Jahre 11 Monate und 30 Tage. (Versuchen Sie es in Ihrem Code).
Athanasios Kataras
1
Upvote! Ich habe eine Lösung gefunden, die ziemlich identisch ist (ich habe DateTime.MinValue.AddTicks (span.Ticks) anstelle von + verwendet, aber das Ergebnis ist das gleiche und Ihres hat ein paar Zeichen weniger Code).
Makotosan
4
Sie haben ganz recht, das ist es nicht. Aber wenn es so wäre, wäre das das Ergebnis. Warum spielt es eine Rolle? Das tut es nicht. In beiden Fällen springen oder nicht, dann gibt es Beispiele, bei denen dies nicht funktioniert. Das wollte ich zeigen. Das DIFF ist korrekt. Die Spanne berücksichtigt Schaltjahre. Das Hinzufügen zu einem Basisdatum ist dies jedoch nicht. Probieren Sie die Beispiele im Code aus und Sie werden sehen, dass ich Recht habe.
Athanasios Kataras
28

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;
    }
};
2601
quelle
28

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-Ybwenn das Datum bereits erreicht Yn-Yb-1ist, oder nicht.

a) Wenn Mn<Mbja-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=Mbund Dn<Dbhaben wir31*(Mn - Mb) = 0 and -30 <= Dn-Db <= -1

Wieder mit ganzzahliger Division

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

c) Wenn Mn>Mbja31 <= 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=Mbund Dn>Db, haben wir 31*(Mn - Mb) = 0 and 1 <= Dn-Db <= 30

Wieder mit ganzzahliger Division

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

e) Wenn Mn=Mbund Dn=Dbhaben wir31*(Mn - Mb) + Dn-Db = 0

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

Matthew Watson
quelle
3
Ich bin auf diese lange und nervige Diskussion gestoßen, und Ihre Lösung ist ein wirklich netter und kleiner Ansatz. Danke, dass
du
25

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++;
    }

}
Jon
quelle
21

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.

rockXrock
quelle
20

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.");
Benutzer181261
quelle
TimeSpan war meine erste Wahl, stellte jedoch fest, dass es keine TotalYears-Eigenschaft bietet. Sie könnten es versuchen (ts.TotalDays / 365) - aber es berücksichtigt keine Schaltjahre usw.
Lazlow
19

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:

  • In Großbritannien und Hongkong: Es ist der ordinale Tag des Jahres. Am nächsten Tag, dem 1. März, haben Sie Geburtstag.
  • In Neuseeland: Es ist der Vortag, der 28. Februar für die Zwecke der Fahrerlaubnis und der 1. März für andere Zwecke.
  • Taiwan: Es ist der 28. Februar.

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:

  • Eine westliche (europäische) Altersrechnung, und
  • Ein Kalender wie der Gregorianische Kalender, der am Ende eines Monats einen einzelnen Schalttag einfügt.
Nicholas Carey
quelle
19
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.

Dakotah Hicock
quelle
18

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 DateTimeund 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 :)

flindeberg
quelle
Was ist TickFactor ?
Vor
17

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);
Rajeshwaran SP
quelle
Mit String Concat wäre dies möglich: 47 Jahre 11 Monate 7 Tage
JoshYates1980
16

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;
}



mjb
quelle
Es ist heute! (Der nächste ist in vier Jahren.)
Peter Mortensen
15

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.

Knickerless-Noggins
quelle
14

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"; ;
}
Doron
quelle
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;
}
AEMLoviji
quelle
10

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
Benutzer687474
quelle
10

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 IClockanstelle der Verwendung SystemClock.Instancewürde die Testbarkeit verbessern.

  • Die Zielzeitzone wird sich wahrscheinlich ändern, daher möchten Sie auch einen DateTimeZoneParameter.

Siehe auch meinen Blog-Beitrag zu diesem Thema: Umgang mit Geburtstagen und anderen Jubiläen

Matt Johnson
quelle
Sind Sie mit Noda Time verbunden?
Zimano
Ich habe Beiträge dazu geleistet, aber es ist hauptsächlich Jon Skeets.
Matt Johnson-Pint
9

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;
}
Dylan Hayes
quelle
9

SQL-Version:

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  
Xenedia
quelle
8

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.

cdiggins
quelle