![]() |
Alter fehlerfrei errechnen
Himitsu, Sir Rufo und Wolfgang Mix zeigen in diesem Tutorial, wie man das Alter einer Sache oder einer Person fehlerfrei bestimmen kann.
In Datenbanken kommt es häufig vor, dass man zu einer Person das Alter bestimmen muss. Die Funktionen von (nicht nur) Delphi ![]() ![]() Das wird auch klar, wenn man sich die OH von Delphi anschaut: Zitat:
Wenn es um die Bestimmung von ganzzahligen Jahren zwischen 2 Daten geht, hilft nachstehend beschriebener Pseudo-Algorithmus von Wolfgang Mix weiter, der plattformunabhängig fehlerfreie Rückgabewerte liefert. Alternativ kann man auch mit der neu codierten Funktion von YearsBetween von himitsu und Sir Rufo ermitteln. (siehe unten) Wer mit Jahresteilen mit Jahr >= 1 weiterrechnen muss, ist mit himitsus und Sir Rufos Code bestens bedient. Sie zeigen eindrucksvoll, dass ein bisschen mehr Code erforderlich ist, wenn man mit YearsBetween korrekt rechnen will. Der Algorithmus, den Wolfgang Mix hier vorstellt, lässt sich am einfachsten ohne PC am Schreibtisch begreifen: Man nehme ein Blatt Papier und einen Stift und mache folgendes: 1. Schreibe das heutige Datum im Format YYYYMMDD (ohne Trennzeichen) auf. 2. Schreibe darunter Deinen Geburtstag im selben Format. 3. Bilde die Differenz dieser beiden LongInt-Zahlen. 4. Die Ziffern 1-4 (meist nur 3 und 4) ergeben das Alter in ganzen Jahren. Führende Nullen weglassen! Dieser Algorithmus funktioniert plattformunabhängig in jeder Programmier-Sprache und wurde von Wolfgang Mix erstmals 2/1992 in DOS International (heute PC-Magazin) vorgestellt, ist aber im WEB nicht mehr greifbar gewesen. Beispiel 1: Das Systemdatum sei 24.1.2010 und mein Geburtstag 25.1.1950 1. 20100124 2. 19500125 ________ 3./4. 00599999 Ziffern 3 und 4 ergeben das Alter: 59 Beispiel 2: Einen Tag später ergibt sich folgendes: 1. 20100125 2. 19500125 ________ 3./4. 00600000 Ziffern 3 und 4 ergeben das Alter: 60 Vorteil des Verfahrens: In den meisten Programmiersprachen ist dieser Pseudocode als Einzeiler codierbar... Außerdem braucht mach sich keine Gedanken um Schaltjahresregeln zu machen. Das Ganze funktioniert sogar, wenn etwas älter als 1000 Jahre wird. Zu beachten ist allerdings, dass ein Datum zuerst in seine Einzelkomponenten zerlegt werden muss oder in diesen vorliegen muss, damit das Verfahren angewendet werden kann. Zur Umsetzung in Delphi-Code werden hier ein paar Beispiele angefügt, die hier in der DP entstanden sind.
Delphi-Quellcode:
//DeddyH – Delphi - PRAXiS
function Age(BirthDate: TDate): integer; var y1,y2,m1,m2,d1,d2: Word; begin SysUtils.DecodeDate(date,y1,m1,d1); SysUtils.DecodeDate(BirthDate,y2,m2,d2); Result := ((y1 * 10000 + m1 * 100 + d1) - (y2 * 10000 + m2 * 100 + d2)) div 10000; end; Für Datenbankanwendungen hat Omata folgende Lösung zur Umsetzung des Pseudocodes beigetragen:
SQL-Code:
SELECT ( ( YEAR(GETDATE()) * 10000
+ MONTH(GETDATE()) * 100 + DAY(GETDATE())) - ( YEAR(geburtsdatum) * 10000 + MONTH(geburtsdatum) * 100 + DAY(geburtsdatum))) / 10000 AS "alter" FROM tabelle MySQL:
SQL-Code:
SELECT ( ( YEAR(CURRENT_DATE()) * 10000
+ MONTH(CURRENT_DATE()) * 100 + DAY(CURRENT_DATE())) - ( YEAR(geburtsdatum) * 10000 + MONTH(geburtsdatum) * 100 + DAY(geburtsdatum))) DIV 10000 AS "alter" FROM tabelle Firebird:
SQL-Code:
SELECT ( ( EXTRACT(YEAR FROM CURRENT_DATE) * 10000
+ EXTRACT(MONTH FROM CURRENT_DATE) * 100 + EXTRACT(DAY FROM CURRENT_DATE)) - ( EXTRACT(YEAR FROM geburtsdatum) * 10000 + EXTRACT(MONTH FROM geburtsdatum) * 100 + EXTRACT(DAY FROM geburtsdatum))) / 10000 AS "alter" FROM tabelle Shmia zeigt hier, wie man Aufgabe für einen binär rechnenden Computer optimiert.
Delphi-Quellcode:
Erklärung:
function Age(BirthDate: TDate): integer;
var y1,y2,m1,m2,d1,d2: Word; begin SysUtils.DecodeDate(date,y1,m1,d1); SysUtils.DecodeDate(BirthDate,y2,m2,d2); { Result := ((y1 * 10000 + m1 * 100 + d1) - (y2 * 10000 + m2 * 100 + d2)) div 10000; } Result := (((y1 shl 4 or m1) shl 5 or d1) - ((y2 shl 4 or m2) shl 5 or d2)) shr 9; end; ein Monat hat maximal 31 Tage - also darf man auch mit 32 anstatt mit 100 multiplizieren. Das entspricht einem Linksshift um 5 Bits. Ein Jahr hat 12 Monate. Also darf man auch mit 16 multiplizieren. Das entspricht einem Linksshift um 4 Bits. Der Rechtsshift um 9 macht alles wieder rückgängig und lässt dabei den Rest wie bei einer Division verschwinden Himitsu und Sir Rufo haben die Funktion YearsBetween neu programmiert, damit man nicht nur mit ganzen Jahren, sondern auch mit Jahresteilen richtig rechnen kann:
Delphi-Quellcode:
//himitsu - Delphi-PRAXiS
// -------------------------------------------------------------------------- // Tauscht die übergebenen Datumsangaben, damit ANow <= AThen // -------------------------------------------------------------------------- procedure CheckedSwap( Var ANow, AThen : TDateTime ); Inline; Var Temp : TDateTime; Begin If ANow <= AThen Then Exit; Temp := ANow; ANow := AThen; AThen := Temp; End; ///himitsu und Sir Rufo - Delphi - PRAXiS // -------------------------------------------------------------------------- // Ermittelt die Jahre zwischen zwei Datumswerten // -------------------------------------------------------------------------- function YearsBetween(ANow: TDateTime; AThen: TDateTime): Integer; var Yn, Yt, Mn, Mt, Dn, Dt: Word; Begin CheckedSwap(ANow, AThen); DecodeDate(ANow, Yn, Mn, Dn); DecodeDate(AThen, Yt, Mt, Dt); Result := Yt - Yn; If (Mt < Mn) or ((Mt = Mn) and ((Dt < Dn))) Then Dec(Result); End; Beispiel 1: AThen = 25.08.2002 > ANow = 21.08.2008 Result = 2008 - 2002 Result = 6 Jahre (+4 Tage) Anders herum: AThen = 21.08.2002 > ANow = 25.08.2008 Result = 2008 - 2002 Result = 6 Jahre (-4 Tage) 8=8 und 21<25 ... also Monat ist gleich und Tag ist kleiner bedeutet also, daß zwischen 25.08. und 21.08. kein ganzes Jahr liegt, weswegen dieses unvollständige Jahr vom Ergebnis abgezogen wird if ... or ((8 = 8) and (21 < 25)) then Result := Result - 1; Result = 5 ganze Jahre Dieses fällt ganz besonders bei extremeren Werten auf. Beispiel 2: ANow = 1.12.2002 > AThen = 02.01.2004 Result = 2004 - 2002 = 2 if (1 < 12) or ... then Result := Result - 1; Result = nur 1 ganzes Jahr Unterschied (genauer gesagt 1 Jahr und 2 Tage) Beispiel 3: Delphis YearsBetween macht Fehler z.B für ANow = 01.01.2009 AThen = 01.01.2010 Result = 0 Jahre, richtig wäre 1 Jahr |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:08 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz