
Datumswerte als Integer
Datumswerte bestehen in CF aus Datum und Uhrzeit. Das führt in der Praxis
gelegentlich zu Problemen
wenn eigentlich nur das Datum und nicht die Uhrzeit benötigt wird.
Hat man beispielsweise Datumswerte mit gleichem Datum und verschiedenen
Uhrzeiten lassen diese sich nicht einfach
vergleichen denn der 13.2.2002 14:00 ist programmtechnisch gesehen nicht
gleich 13.2.2002 18:10.
Manchmal wäre aber ganz praktisch, wenn man auf die Uhrzeit verzichten
könnte.
Will man beispielsweise News in einer Datenbank speichern und auslesen
wird die Uhrzeit des Speicherns keine Rolle spielen soll. Man könnte dann
leicht alle News eines Tages ermitteln,
ohne beachten zu müssen, dass der Tag ja normalesweise von 00:00:00 Uhr bis
23:59:59 Uhr läuft.
Auch in einer Anwendung zur Speicherung der Urlaubszeit eines Mitarbeiters
würde eine Uhrzeit nur stören, denn man hat ja
normalerweise den ganzen Tag Urlaub.
Natürlich könnten wir in diesen Fällen die Uhrzeit immer mit 00:00:00
kennzeichnen.
Aber warum die Uhrzeit speichern, wenn wir sie nicht
benötigen?
Da auch nicht jede Datenbank eine Datentype für Datum ohne Uhrzeit
anbietet (z.b. SQL-Server), kann man sich mit
einem kleinen Trick behelfen, indem man sich seinen eigenen
Datetype für Datumswerte ohne Uhrzeit bastelt. Zusätzlich kann man dadurch
sogar SQL-Performance gewinnen
und Datenbankplatz sparen.
Dafür benötigen wir lediglich zwei Funktionen sowie ein Referenzdatum.
Die erste Funktion date2int() berechnet aus dem angegebenen Datum die
Differenz zu einem Referenzdatum und liefert das
Ergebniss als Intergerwert zurück.
Die zweite Funktion int2date() wandelt einen übergebenen Integerwert wieder
in
ein Datum zurück, indem der Integerwert wieder auf
das Referenzdatum addiert wird.
Seit CF5 sind nun glücklicherweise eigenen Funktionen möglich, so dass wir
die Programmlogik auch direkt als CF-Funktionen implementieren können:
Die 3. Funktion int2DEDate() ist prinzipiell nicht nötig, dient aber zur
Erleichterung der Anzeige, da sie einen Integerwert gleich
in deutschen Format ausgibt.
<CFSCRIPT>
function date2int(date) {
return datediff("d","1900-01-01",date);
}
function int2date(i) {
return dateadd("d",i,"1900-01-01");
}
function int2DEDate(i) {
return DateFormat(dateadd("d",i,"1900-01-01"),"dd.mm.yy");
}
</CFSCRIPT>
Das ganze lässt sich dann so testen:
<cfset datum=now()>
<cfset myInt=date2int(datum)>
<cfset datum2=int2date(myInt)>
<cfset datum3=int2deDate(myInt)>
<cfoutput>
Ausgansdatum:#datum#<br>
Integerwert:#myInt#<br>
neues Datum:#datum2#<br>
deutsches Datum:#datum3#<br>
</cfoutput>
<cfabort>
Damit könnten wir News ganz einfach inkl. des aktuellen Datums speicherns:
<cfquery ...>
insert into news (text,datum)
values(text,#date2int(now())#)
</cfquery>
Alle News vom aktuellen Tag könnte man beispielsweise so ermitteln:
<cfquery ...>
select * from news where datum=#date2int(now())#
</cfquery>
Zur Anzeige des Datums müsste man dann schreiben:
<cfoutput query="news">
#int2DEDate(news.datum)#:#news.text#<br>
</cfoutput>
Speichert man Datumswerte als Integer anstatt als Datumswerte in einer
Datenbank spart das zusätzlich Speicherplatz, den der redundante Timewert fällt ja weg.
Ein Datetimetype ist z.B. beim SQL-Server 8 Byte lang (4 byte Datum, 4 Byte
Uhrzeit).
Ein Integer-Type benötigt 4 Byte. Das macht bei 1 Million Einträgen eine
Einsparung von ca. 4 MB.
Die Datenbank wird also dadurch etwas kleiner und die Geschwindigkeit
der Abfragen steigt (macht natürlich nicht so wahnsinnig viel aus, aber der Mensch freut sich :-) )
Steffen Goldfuss steffen@goldfuss.de - 21.02.2002