| 

.NET C# Java Javascript Exception

4
Wie berechne ich das Alter einer Person? Gegeben ist der Geburtstag und das heutige Datum.
31.08.2009
Felix 490 1 9
Felix 490 1 9
Wie liegen denn die Daten vor? Tag, Monat, Jahr in einzelnen Variablen gespeichert, oder im DateTime Typ?
Shelling 31.08.2009
Verdammt bist du schnell :) Wollte die Frage als Referenz festhalten, weil ich nichts brauchbares bei Google gefunden habe.
Felix 31.08.2009
Falls du auch eine Lösung hast, nur her damit!
Felix 31.08.2009
7 Antworten
6
Dazu kann man folgenden Code verwenden, der auch in der codekicker-Codebase verwendet wird:

public static int GetAge(DateTime dateOfBirth, DateTime now)
{
var nowDate = now.Date;

if (dateOfBirth > nowDate) throw new ArgumentException();
if (dateOfBirth == nowDate) return 0;

var yearDiff = nowDate.Year - dateOfBirth.Year;
return dateOfBirth.DayOfYear <= nowDate.DayOfYear ? yearDiff : yearDiff - 1;
}

Das Alter ist also die Differenz der seit der Geburt vergangenen Jahre mit einer Korrektur, je nachdem, ob das heutige Datum vor oder nach dem Geburtstag liegt.
31.08.2009
Felix 490 1 9
Und damit ist ein weiterer Teil von codekicker open source geworden ;-)
Marvin Steppat 31.08.2009
DayOfYear funktioniert nicht nach dem 28. Feb! Wenn eines der beiden Jahre ein Schaltjahr ist und das andere nicht, ergibt sich z.B. für den 1. März entweder 61 (Schaltjahr) oder 60 (kein Schaltjahr).
BeachBlocker 10.09.2009
2
2 Anmerkungen meinerseits:

#START:Klugscheißerei

1. Vom 'now'-Parameter wird die Zeit gestripped, jedoch nicht vom 'dateOfBirth'-Parameter. Damit sind die folegnden 2 if-statements nicht wirklich korrekt:

if (dateOfBirth > nowDate) throw new ArgumentException();
if (dateOfBirth == nowDate) return 0;


2. Es ist nicht sinnvoll eine ArgumentException zu werfen, die nicht sagt welches Argument falsch ist. Desweiteren ist es sinnvoller eine ArgumentOutOfRangeException zu werfen, da das Argument ja nicht einen best. Wertebereich entspricht den du erwartest. Sinnvoller wäre es in etwa so:

throw new ArgumentOutOfRangeException("dateOfBirth", dateOfBirth, "'dateOfBirth' is larger than 'now'");


#END:Klugscheißerei
07.09.2009
Scordo 31 1 1
2
Hallo,
wie wäre es mit folgendem vorgehen:

public int GetAgeAsInt(DateTime dateOfBirth)
{
return this.GetAgeAsInt(dateOfBirth, DateTime.Now);
}
public int GetAgeAsInt(DateTime dateOfBirth, DateTime referenceDate)
{
if (dateOfBirth > referenceDate)
throw new ArgumentOutOfRangeException("dateOfBirth", dateOfBirth, "'dateOfBirth' is larger than the given reference date");

return referenceDate.Year - dateOfBirth.Year;
}


Wird nur das Alter angegeben, berechnet die Methode immer mit dem aktuellen Datum. Alternativ kann ein zweites Datum übergeben werden mit dem dann gerechnet wird. Die Fehlerbehandelung habe ich anhand des Kommentar von Scordo eingebaut.
Die Methode könnte z.B. in ein Stammdatenobjekt verwendet werden in dem das Geburtsdatum als Property hinterlegt ist.
Viel Spass damit.
Gruß
07.09.2009
Hagen Deike 81 1 1
1
Hi,
was macht denn ihr für Umstände ein Alter auszurechnen?
Meiner Meinung nach langt folgendes völlig aus:

TimeSpan diff = DateTime.Now - DateTime.Parse("1960-09-10");
double age = diff.TotalDays/365.25;


Grüßle
10.09.2009
Scout 1,4k 1 8
Scout 1,4k 1 8
hab das erst heute gelesen, aber dein eintrag ist der einzig vernünftige zu dem thema.
nabuchodonossor 11.03.2011
1
Sehe ich anders. Die Lösung ignoriert, dass "Alter in Jahren" im alltäglichen Gebrauch eine Ganzzahl ist, die am jeweiligen Jahrestag hochgezählt wird. Dazu müsste man hier runden - aber nach welcher Regel? Am anschaulichsten wird das, wenn man Schaltjahre betrachtet: Die Differenz zwischen dem 1.3.1959 und dem 29.02.1960 sowie dem 1.3.1960 und dem 1.3.1961 ist exakt gleich, nämlich 365 Tage. Trotzdem wird man in dem einen Fall 0 Jahre als Alter angeben und in dem anderen 1. Dies kann das angegebene Verfahren nicht abbilden.
Matthias Hlawatsch 11.03.2011
0
Damit berechne ich die Differenz in Jahren zw. 2 Datumswerten. Kann natürlich auch zur Berechnung des Alters verwendet werden.

public static int YearSpan(DateTime fromDate, DateTime toDate)
{
if (fromDate.Date >= toDate.Date)
return 0;

string toDateStr = toDate.Date.ToString("yyyyMMdd");
string fromDateStr = fromDate.Date.ToString("yyyyMMdd");

return (int) (Convert.ToInt32(toDateStr) - Convert.ToInt32(fromDateStr)) / 10000;

}
08.09.2009
0
Ich dachte zuerst bah das ich doch einfach aber nach dem ich versuchte meinen Gedanken in Code zu giessen fiel mir auf dass es doch nicht so "easy" ist.
TimeSpan liefert nur Days aus gutem Grund, die Tage sind je nach Monate/Jahre unterschiedlich. Das alter in Jahre/Monate/Tage genau um zu setzen ist per se nicht direkt möglich. Ich habe es so umgesetzt:

  • eine Klasse DateSpan den kalendarische pendant zu TimeSpan definiert (ohne SchnickSchnak)
  • enine Age extension Methode für DateTime hinzugefügt.


Wenn den Code angewendet werden sollte:
DateTime date = DateTime.ParseExact("1977-08-31", "yyyy-MM-dd", null);
Console.Out.WriteLine("Age: {0}", date.Age());


Hier der Code für DateSpan, bitte selber in einem Passenden "namespace" packen. Den Unterschied in Jahre ist relativ einfach, ganze Monate auch. Wie viele Tage ist Definitionssache. Ich definiere es so: ich addiere die Tage vom Ziel Monat zu den restlichen Tage vom Anfangsmonat und substrahiere eventuell den Anzahl Tage im Ziel Monat je nachdem of dessen Zahl überschritten ist oder nicht. Es kommt mir so am deutlichste vor. Bitte melden, wenn jemandem eine bessere Idee hat.

public class DateSpan
{
public DateSpan(DateTime fromDate, DateTime toDate)
{
if (fromDate < toDate) {
FromDate = fromDate;
ToDate = toDate;
Negative = false;
} else {
FromDate = toDate;
ToDate = fromDate;
Negative = true;
}
int remainingDaysInStartMonth = DateTime.DaysInMonth(FromDate.Year, FromDate.Month) - FromDate.Day + 1;
Days += ToDate.Day + remainingDaysInStartMonth;
int daysInMonth = DateTime.DaysInMonth(ToDate.Year, ToDate.Month);
if (Days > daysInMonth)
Days -= daysInMonth;
if (ToDate.Day < FromDate.Day)
{
--Months;
}
Months += ToDate.Month - FromDate.Month;
if (Months < 0)
{
Months += 12;
--Years;
}
Years += ToDate.Year - FromDate.Year;
if (Years < 0)
throw new Exception("Unexpected state");
}

public Boolean Negative { get; private set; }
public DateTime FromDate { get; private set; }
public DateTime ToDate { get; private set; }
public int Years { get; private set; }
public int Months { get; private set; }
public int Days { get; private set; }

public override string ToString()
{
return String.Format("{0} years, {1} months, {2} days", Years, Months, Days);
}
}

public static DateSpan Age(this DateTime anEvent)
{
return new DateSpan(anEvent, DateTime.Now);
}


Die Millisekunden, Sekunden, Minute und Stunden habe ich weg gelassen. Man muss ja nicht gleich übertreiben, wer es machen will soll mit den Milliseconds anfangen und die Überläufe berücksichtigen z.B.:
Minutes += ToDate.Minute - FromDate.Minute;
if (Minutes < 0) {
Minutes += 60;
--Hours;
}
09.09.2009
jdehaan 424 1 7
jdehaan 424 1 7

Stelle deine .net-Frage jetzt!