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.
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 yearif(birthdate.Date> today.AddYears(-age)) age--;
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:
publicstaticInt32GetAge(thisDateTime 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;}
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.
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:
Listenpunkt
int age =irthDate.Age ();
publicstaticclassDateTimeExtensions{/// <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>publicstaticintAge(thisDateTime birthDate){returnAge(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>publicstaticintAge(thisDateTime 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:
classProgram{staticvoidMain(string[] args){RunTest();}privatestaticvoidRunTest(){DateTime birthDate =newDateTime(2000,2,28);DateTime laterDate =newDateTime(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();}}
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.)
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:
publicstaticintGetAge(DateTime birthDate){DateTime n =DateTime.Now;// To avoid a race condition around midnightint 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 :-)
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 timeTimeSpan age = today - birth;//.NET FCL should guarantee this as precisedouble ageInDays = age.TotalDays;//total number of days ... also precisedouble daysInYear =365.2425;//statistical value for 400 yearsdouble 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 yearsif(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:
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.
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.
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 =newDateTime(2000,3,1);int age =(int)Math.Floor((DateTime.Now- birthDate).TotalDays/365.25D);
Dies gibt "mehr Details" zu dieser Frage. Vielleicht ist es das, wonach Sie suchen
DateTime birth =newDateTime(1974,8,29);DateTime today =DateTime.Now;TimeSpan span = today - birth;DateTime age =DateTime.MinValue+ span;// Make adjustment due to MinValue equalling 1/1/1int 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 wellConsole.Write("{0} years, {1} months, {2} days", years, months, days);
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;publicpartialclassUserDefinedFunctions{[SqlFunction(DataAccess=DataAccessKind.Read)]publicstaticSqlInt32CalculateAge(string strBirthDate){DateTime dtBirthDate =newDateTime();
dtBirthDate =Convert.ToDateTime(strBirthDate);DateTime dtToday =DateTime.Now;// get the difference in yearsint years = dtToday.Year- dtBirthDate.Year;// subtract another year if we're before the// birth day in the current yearif(dtToday.Month< dtBirthDate.Month||(dtToday.Month== dtBirthDate.Month&& dtToday.Day< dtBirthDate.Day))
years=years-1;int intCustomerAge = years;return intCustomerAge;}};
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.
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:
publicvoidLoopAge(DateTime myDOB,DateTimeFutureDate){int years =0;int months =0;int days =0;DateTime tmpMyDOB =newDateTime(myDOB.Year, myDOB.Month,1);DateTime tmpFutureDate =newDateTime(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 dayif(DateTime.IsLeapYear(myDOB.Year)&& myDOB.Month==2&& myDOB.Day==29){//but only if the future date is less than 1st Marchif(FutureDate>=newDateTime(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.
publicstaticstringHowOld(DateTime birthday,DateTime now){if(now < birthday)thrownewArgumentOutOfRangeException("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 weekDateTime 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");}}}elseif(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]publicvoidTestAge(){string age =HowOld(newDateTime(2011,1,1),newDateTime(2012,11,30));Assert.AreEqual("1 year", age);
age =HowOld(newDateTime(2011,11,30),newDateTime(2012,11,30));Assert.AreEqual("1 year", age);
age =HowOld(newDateTime(2001,1,1),newDateTime(2012,11,30));Assert.AreEqual("11 years", age);
age =HowOld(newDateTime(2012,1,1),newDateTime(2012,11,30));Assert.AreEqual("10 months", age);
age =HowOld(newDateTime(2011,12,1),newDateTime(2012,11,30));Assert.AreEqual("11 months", age);
age =HowOld(newDateTime(2012,10,1),newDateTime(2012,11,30));Assert.AreEqual("1 month", age);
age =HowOld(newDateTime(2008,2,28),newDateTime(2009,2,28));Assert.AreEqual("1 year", age);
age =HowOld(newDateTime(2008,3,28),newDateTime(2009,2,28));Assert.AreEqual("11 months", age);
age =HowOld(newDateTime(2008,3,28),newDateTime(2009,3,28));Assert.AreEqual("1 year", age);
age =HowOld(newDateTime(2009,1,28),newDateTime(2009,2,28));Assert.AreEqual("1 month", age);
age =HowOld(newDateTime(2009,2,1),newDateTime(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(newDateTime(2009,1,31),newDateTime(2009,2,28));Assert.AreEqual("4 weeks", age);
age =HowOld(newDateTime(2009,2,1),newDateTime(2009,2,28));Assert.AreEqual("3 weeks", age);
age =HowOld(newDateTime(2009,2,1),newDateTime(2009,3,1));Assert.AreEqual("1 month", age);
age =HowOld(newDateTime(2012,11,5),newDateTime(2012,11,30));Assert.AreEqual("3 weeks", age);
age =HowOld(newDateTime(2012,11,1),newDateTime(2012,11,30));Assert.AreEqual("4 weeks", age);
age =HowOld(newDateTime(2012,11,20),newDateTime(2012,11,30));Assert.AreEqual("1 week", age);
age =HowOld(newDateTime(2012,11,25),newDateTime(2012,11,30));Assert.AreEqual("5 days", age);
age =HowOld(newDateTime(2012,11,29),newDateTime(2012,11,30));Assert.AreEqual("1 day", age);
age =HowOld(newDateTime(2012,11,30),newDateTime(2012,11,30));Assert.AreEqual("just born", age);
age =HowOld(newDateTime(2000,2,29),newDateTime(2009,2,28));Assert.AreEqual("8 years", age);
age =HowOld(newDateTime(2000,2,29),newDateTime(2009,3,1));Assert.AreEqual("9 years", age);Exception e =null;try{
age =HowOld(newDateTime(2012,12,1),newDateTime(2012,11,30));}catch(ArgumentOutOfRangeException ex){
e = ex;}Assert.IsTrue(e !=null);}
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.
publicintAgeInYears(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);elseif(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.
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 birthdayvar 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 enddouble 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 endint 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 :)
Ich habe eine angepasste Methode zur Berechnung des Alters sowie eine Bonusvalidierungsnachricht für den Fall, dass dies hilfreich ist:
publicvoidGetAge(DateTime dob,DateTime now,outint years,outint months,outint days){
years =0;
months =0;
days =0;DateTime tmpdob =newDateTime(dob.Year, dob.Month,1);DateTime tmpnow =newDateTime(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 >=newDateTime(now.Year,3,1))
days++;}privatestringValidateDate(DateTime dob)//This method will validate the date{intYears=0;intMonths=0;intDays=0;GetAge(dob,DateTime.Now,outYears,outMonths,outDays);if(Years<18)
message =Years+" is too young. Please try again on your 18th birthday.";elseif(Years>=65)
message =Years+" is too old. Date of Birth must not be 65 or older.";elsereturnnull;//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.
staticstringCalcAge(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";;}
// ----------------------------------------------------------------------publicvoidCalculateAgeSamples(){PrintAge(newDateTime(2000,02,29),newDateTime(2009,02,28));// > Birthdate=29.02.2000, Age at 28.02.2009 is 8 yearsPrintAge(newDateTime(2000,02,29),newDateTime(2012,02,28));// > Birthdate=29.02.2000, Age at 28.02.2012 is 11 years}// CalculateAgeSamples// ----------------------------------------------------------------------publicvoidPrintAge(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.
staticintGetAge(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 =newLocalDate(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.
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.
publicstaticDictionary<string,int>CurrentAgeInYearsMonthsDays(DateTime? ndtBirthDate,DateTime? ndtReferralDate){//----------------------------------------------------------------------// Can't determine age if we don't have a dates.//----------------------------------------------------------------------if(ndtBirthDate ==null)returnnull;if(ndtReferralDate ==null)returnnull;DateTime dtBirthDate =Convert.ToDateTime(ndtBirthDate);DateTime dtReferralDate =Convert.ToDateTime(ndtReferralDate);//----------------------------------------------------------------------// Create our Variables//----------------------------------------------------------------------Dictionary<string,int> dYMD =newDictionary<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.
publicintAgeInYears(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.
Antworten:
Eine leicht verständliche und einfache Lösung.
Dies setzt jedoch voraus, dass Sie nach der westlichen Idee des Alters suchen und keine ostasiatische Abrechnung verwenden .
quelle
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.
Löschen Sie die letzten 4 Ziffern =
28
.C # -Code:
Oder alternativ ohne die gesamte Typkonvertierung in Form einer Erweiterungsmethode. Fehlerprüfung weggelassen:
quelle
20180101 - 20171231 = 8870
. Lassen Sie die letzten 4 Ziffern fallen und Sie haben (eine implizite)0
für das Alter. Wie bist du gekommen1
?Hier ist ein Testausschnitt:
Hier haben Sie die Methoden:
quelle
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 ();
Führen Sie nun diesen Test aus:
Das Beispiel für ein kritisches Datum lautet:
Geburtsdatum: 2000-02-29 Späteres Datum: 2011-02-28 Alter: 11
Ausgabe:
Und für den späteren Zeitpunkt 28.02.2012:
quelle
date.Age(other)
?Mein Vorschlag
Das Jahr scheint sich zum richtigen Zeitpunkt zu ändern. (Ich habe bis zum Alter von 107 Jahren vor Ort getestet.)
quelle
days in a year = 365.242199
Eine andere Funktion, nicht von mir, sondern im Web gefunden und ein wenig verfeinert:
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 :-)
quelle
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:
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:
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:
quelle
Hier ist ein Einzeiler:
quelle
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.
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 derDateTime.Now
Vollständigkeit halber übergeben wird.quelle
Der beste Weg, den ich aufgrund von Schaltjahren und allem kenne, ist:
quelle
Ich benutze das:
quelle
Dies gibt "mehr Details" zu dieser Frage. Vielleicht ist es das, wonach Sie suchen
quelle
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:
quelle
Hier ist noch eine andere Antwort:
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:
quelle
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:
quelle
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.
Diese Implementierung wurde unter Testfällen bestanden.
Hoffe es ist hilfreich.
quelle
Halte es einfach (und möglicherweise dumm :)).
quelle
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.
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:
Es ist zu beachten, dass dieser Code Folgendes voraussetzt:
quelle
Ich bin mir nicht sicher, wie genau es Ihnen zurückgegeben werden soll, also habe ich gerade eine lesbare Zeichenfolge erstellt.
quelle
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 NormalisierungDateTime
und ohne Berücksichtigung relativistischer Effekte):Auf christliche Weise zur Berechnung des Alters in Jahren:
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"):
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):
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 :)
quelle
Hier ist eine Lösung.
quelle
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.
quelle
Ich habe eine angepasste Methode zur Berechnung des Alters sowie eine Bonusvalidierungsnachricht für den Fall, dass dies hilfreich ist:
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:
Denken Sie daran, dass Sie die Nachricht beliebig formatieren können.
quelle
Wie wäre es mit dieser Lösung?
quelle
quelle
Der folgende Ansatz (Auszug aus der Zeitperiodenbibliothek für die .NET- Klasse DateDiff ) berücksichtigt den Kalender der Kulturinformationen:
Verwendungszweck:
quelle
Diese klassische Frage verdient eine Noda Time- Lösung.
Verwendungszweck:
Sie könnten auch an folgenden Verbesserungen interessiert sein:
Das Eingeben der Uhr als
IClock
anstelle der VerwendungSystemClock.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
quelle
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.
quelle
SQL-Version:
quelle
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.
Ich habe es aus Gründen der Klarheit auch zu einer Funktion gemacht.
quelle