PDA

Vollständige Version anzeigen : Grundsätzliches und Zusammenfassendes über den Datum/Uhrzeit-Datentyp


FW
11.03.2007, 15:44
Die Online-Hilfe liefert zum Datentyp Date folgenden Auszug:
Variablen vom Datentyp Date werden als 64-Bit-Gleitkommazahlen (8 Bytes) nach IEEE gespeichert und können ein Datum im Bereich vom 01. Januar 100 bis zum 31. Dezember 9999 und eine Uhrzeit im Bereich von 0:00:00 bis 23:59:59 speichern.
Somit ist der Datentyp Date nichts anderes, als der Datentyp Double:
Variablen vom Datentyp Double (Gleitkommazahl mit doppelter Genauigkeit) werden als 64-Bit-Gleitkommazahlen (8 Bytes) nach IEEE im Bereich von -1,79769313486231E308 bis -4,94065645841247E-324 für negative Werte und von 4,94065645841247E-324 bis 1,79769313486232E308 für positive Werte gespeichert.
Beim Datentyp Date stehen die Vorkommastellen für die Anzahl der Tage, die seit dem 30.12.1899 vergangen sind:
So liefert CLng(DateSerial(1899,12,30)) den Wert 0 und
Year(0), Month(0), Day(0) die Werte 1899, 12, 30.

Die Nachkommastellen stehen beim Datentyp Date für die vergangenen Sekunden seit 00:00:00
So liefert CDbl(TimeSerial(0,0,1)) den Wert 1,15740740740741E-05, was nichts anderes ist, als der Kehrwert der Anzahl von Sekunden pro Tag: 1 / (24 * 60 * 60) = 1,15740740740741E-05

Somit kann u. a. bei dynamischen DB-Abfragen auf das Formatieren eines Datums oder einer Zeit verzichtet werden:
Statt DCOUNT("datumsfeld","tabelle","datumsfeld=#" & FORMAT$(variablesdatum,"yyyy-mm-dd hh:nn:ss") & "#")
einfach DCOUNT("datumsfeld","tabelle"," datumsfeld =" & Str(CDbl(variablesdatum))), wobei die Str-Funktion hierbei dafür sorgt, dass immer ein Punkt als Dezimaltrenner benutzt wird, um so einen Syntaxfehler, den ein Komma erzeugen würde, zu vermeiden.

Die Int-Funktion schneidet ja bekanntlich die Nachkommastellen einer Gleitkommazahl ab und liefert so den ganzzahligen Anteil einer Gleitkommazahl. Auf ein Datum bezogen heißt das nun, dass die Uhrzeit abgeschnitten wird.
Int(Now()) liefert also den gleichen Wert wie Date()

Mit diesen Erkenntnissen kann nun z. B. auch eine Funktion erstellt werden, die zu einem vorgegebenen Datum die Anzahl von Zeiteinheiten seit dem 30.12.1899 00:00:00 zurückgibt, bzw. die ein vorgegebenes Datum als Gleitkommazahl in Relation zum 30.12.1899 00:00:00 konvertiert:
<div><link href="http://www.ms-office-forum.net/forum/externals/codeconv.css" rel="stylesheet"><span class="TOKEN">Public Function</span> DateTimeToDec(<span class="TOKEN">ByVal</span> strFormat <span class="TOKEN">As</span> String, datVal <span class="TOKEN">As</span> Date) <span class="TOKEN">As</span> <span class="TOKEN">Double</span>
<span class="TOKEN">Dim</span> bytMonthDays <span class="TOKEN">As</span> <span class="TOKEN">Byte</span>
<span class="TOKEN">Dim</span> intYearDays <span class="TOKEN">As</span> <span class="TOKEN">Integer</span>
<span class="TOKEN">Dim</span> lngSecs <span class="TOKEN">As</span> Long, lngDays <span class="TOKEN">As</span> <span class="TOKEN">Long</span>
<span class="TOKEN">Dim</span> datFst <span class="TOKEN">As</span> Date
&nbsp;
strFormat = LCase$(strFormat)
<span class="TOKEN">If</span> Len(strFormat) &lt;&gt; 1 <span class="TOKEN">Or</span> InStr(&quot;ymdhns&quot;, strFormat) = 0 <span class="TOKEN">Then</span> <span class="TOKEN">Exit Function</span>
lngDays = DateDiff(&quot;d&quot;, 0, datVal)
lngSecs = DateDiff(&quot;s&quot;, 0, datVal - lngDays)
Select Case strFormat
Case &quot;y&quot;
datFst = DateSerial(Year(datVal), 1, 1)
lngDays = 2 + DateDiff(&quot;d&quot;, datFst, datVal)
intYearDays = DateDiff(&quot;d&quot;, datFst, DateSerial(Year(datVal), 12, 31)) + 1
DateTimeToDec = DateDiff(&quot;yyyy&quot;, 2, datFst) + lngDays \ intYearDays + (lngDays Mod intYearDays) / intYearDays + (lngSecs \ (24# * 60 * 60) + (lngSecs Mod (24# * 60 * 60)) / (24# * 60 * 60)) / intYearDays
Case &quot;m&quot;
datFst = DateSerial(Year(datVal), Month(datVal), 1)
lngDays = 2 + DateDiff(&quot;d&quot;, datFst, datVal)
bytMonthDays = DateSerial(Year(datVal), Month(datVal) + 1, 0)
DateTimeToDec = DateDiff(&quot;m&quot;, 2, datFst) + lngDays \ bytMonthDays + (lngDays Mod bytMonthDays) / bytMonthDays + (lngSecs \ (24# * 60 * 60) + (lngSecs Mod (24# * 60 * 60)) / (24# * 60 * 60)) / bytMonthDays
Case &quot;d&quot;
DateTimeToDec = lngDays + lngSecs \ (24# * 60 * 60) + (lngSecs Mod (24# * 60 * 60)) / (24# * 60 * 60)
Case &quot;h&quot;
DateTimeToDec = lngDays * 24# + lngSecs \ (60 * 60) + (lngSecs Mod (60 * 60)) / (60 * 60)
Case &quot;n&quot;
DateTimeToDec = lngDays * 24# * 60 + lngSecs \ 60 + (lngSecs Mod 60) / 60
Case &quot;s&quot;
DateTimeToDec = lngDays * 24# * 60 * 60 + lngSecs
<span class="TOKEN">End</span> Select
<span class="TOKEN">End</span> <span class="TOKEN">Function</span></div>

Mit dieser Funktion können insbesondere Uhrzeiten in ihr dezimales Pendant umgerechnet werden:

DateTimeToDec(„h“, TimeSerial(0, 30, 0)) liefert 0,5 (Stunden)
DateTimeToDec(„d“, TimeSerial(6, 0, 0)) liefert 0,25 (Tage)

Es könnte hier noch vieles mehr erwähnt werden, aber es ging mir schwerpunktmäßig darum, den Datentyp Datum/Zeit ein wenig zu entzaubern und aufzuzeigen, dass mit diesem Datentyp auch ganz normal gerechnet werden kann:
DateAdd("d", -1, Now()) ist gleichbedeutend mit Now() - 1
DateAdd(„s“, 1, Now()) ist gleichbedeutend mit Now() + 1 / (24 * 60 * 60)
DateDiff(„d“, datum1, datum2) ist gleichbedeutend mit datum2 - datum1
usw.

Ciao
Frank