{"id":55001620,"date":"2026-10-01T00:00:00","date_gmt":"2026-09-08T11:29:01","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=1620"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Rechnen_mit_Datum_und_Zeit_ohne_Ueberraschungen","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/Rechnen_mit_Datum_und_Zeit_ohne_Ueberraschungen\/","title":{"rendered":"Rechnen mit Datum und Zeit ohne &Uuml;berraschungen"},"content":{"rendered":"<p><b>Datumsberechnungen wirken harmlos, bis die Abfrage die Datens&auml;tze von heute nicht findet, die Kalenderwoche zum Jahreswechsel danebenliegt oder die Summe der Arbeitszeiten pl&ouml;tzlich 07:59 statt 08:00 lautet. Alle drei F&auml;lle haben dieselbe Ursache: Access speichert Datum und Uhrzeit anders, als die angezeigte Darstellung vermuten l&auml;sst. Dieser Beitrag zeigt, was dabei schiefgehen kann, und liefert die Funktionen, die Ihnen die &uuml;blichen Fallen abnehmen.<\/b><\/p>\n<h2>Wie Access Datum und Zeit speichert<\/h2>\n<p>Ein Wert des Datentyps <b>Date<\/b> ist intern eine Flie&szlig;kommazahl vom Typ <b>Double<\/b>. F&uuml;r die in heutigen Anwendungen &uuml;blichen Datumswerte ab dem 30. Dezember 1899 z&auml;hlt der Ganzzahlanteil die Tage seit diesem Ausgangsdatum, der Nachkommaanteil gibt die Tageszeit als Bruchteil eines Tages an. Listing 1 macht das sichtbar.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>DatumAlsZahl()\r\n    <span style=\"color:blue;\">Debug.Print<\/span> CDbl(#4\/5\/2026#)\r\n    <span style=\"color:blue;\">Debug.Print<\/span> CDbl(#4\/5\/2026 12:00:00 PM#)\r\n    <span style=\"color:blue;\">Debug.Print<\/span> CDbl(#4\/5\/2026 6:00:00 AM#)\r\n    <span style=\"color:blue;\">Debug.Print<\/span> CDbl(#12\/30\/1899#)\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Die Ausgabe im Direktbereich:<\/p>\n<pre>46117\r\n46117,5\r\n46117,25\r\n0<\/pre>\n<p>Der 5. April 2026 ist also der Tag Nummer 46117, zw&ouml;lf Uhr mittags entspricht einem halben Tag, sechs Uhr morgens einem Viertel. Aus dieser Darstellung folgen unmittelbar zwei n&uuml;tzliche Rechenregeln: Ein Tag mehr hei&szlig;t schlicht <b>+ 1<\/b>, und die Differenz zweier Datumswerte, multipliziert mit 24, ergibt die Stundenzahl dazwischen. Beachten Sie die Datumsliterale im Code. Zwischen den Rautezeichen erwartet VBA das amerikanische Format mit Monat vor Tag. Schreiben Sie <b>#5.4.2026#<\/b>, wandelt der Editor das stillschweigend in <b>#5\/4\/2026#<\/b> um &#8211; und das ist der 4. Mai, nicht der 5. April.<\/p>\n<h2>Der versteckte Zeitanteil<\/h2>\n<p>Genau hier liegt die h&auml;ufigste Fehlerquelle &uuml;berhaupt. Ein Feld vom Typ Datum\/Uhrzeit, das mit <b>Now<\/b> gef&uuml;llt wurde, enth&auml;lt eben auch die Uhrzeit. Die Prozedur in Listing 2 f&uuml;hrt vor, was das f&uuml;r einen Vergleich bedeutet.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>ZeitanteilFalle()\r\n    <span style=\"color:blue;\">Dim <\/span>datGespeichert<span style=\"color:blue;\"> As Date<\/span>\r\n    datGespeichert = #4\/5\/2026 9:37:12 AM#\r\n    <span style=\"color:blue;\">Debug.Print<\/span> datGespeichert = #4\/5\/2026#\r\n    <span style=\"color:blue;\">Debug.Print<\/span> Int(datGespeichert) = #4\/5\/2026#\r\n    <span style=\"color:blue;\">Debug.Print<\/span> DateValue(datGespeichert) = #4\/5\/2026#\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Hier ist die Ausgabe dieser Prozedur:<\/p>\n<pre>Falsch\r\nWahr\r\nWahr<\/pre>\n<p>Der erste Vergleich scheitert, weil 46117,4008 nun einmal nicht 46117 ist. F&uuml;r aktuelle, positive Datumswerte schneiden sowohl <b>Int<\/b> als auch <b>DateValue<\/b> den Zeitanteil ab; <b>DateValue<\/b> dr&uuml;ckt die fachliche Absicht deutlicher aus. In einer Abfrage sollten Sie allerdings keine der beiden Funktionen auf das Feld anwenden, weil Access dann f&uuml;r jeden Datensatz rechnen muss und den Index nicht mehr nutzen kann. Formulieren Sie stattdessen einen Bereich, wie ihn foglendes Listing zeigt:<\/p>\n<pre>SELECT *\r\nFROM tblAuftraege\r\nWHERE Erfasst &gt;= #2026-04-05#\r\n    AND Erfasst &lt; #2026-04-06#<\/pre>\n<p>Die obere Grenze steht bewusst auf <b>kleiner als der Folgetag<\/b> und nicht auf <b>Between<\/b>. Ein <b>Between #2026-04-05# And #2026-04-06#<\/b> w&uuml;rde die Datens&auml;tze vom 6. April um Punkt Mitternacht mit einschlie&szlig;en, weil <b>Between<\/b> an beiden Enden einschlie&szlig;end arbeitet.<\/p>\n<h2>Datumsangaben in SQL-Ausdr&uuml;cke einbauen<\/h2>\n<p>Setzen Sie eine solche Bedingung per VBA zusammen, brauchen Sie das Datum als Zeichenkette. Ein schlichtes Verketten mit dem Datumswert ist problematisch, weil VBA dabei gew&ouml;hnlich ein von den Regionaleinstellungen abh&auml;ngiges Datumsformat erzeugt und Access den 5. April dann als 4. Mai liest. Die Funktion <b>SqlDatum<\/b> aus Listing 2 nimmt Ihnen die Umwandlung ab.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>SqlDatum(ByVal varDatum<span style=\"color:blue;\"> As Variant<\/span>, <span style=\"color:blue;\">Optional<\/span> ByVal blnMitZeit<span style=\"color:blue;\"> As Boolean<\/span> = <span style=\"color:blue;\">False<\/span>)<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">If <\/span>IsNull(varDatum)<span style=\"color:blue;\"> Then<\/span>\r\n        SqlDatum = \"Null\"\r\n    <span style=\"color:blue;\">Else<\/span>If <span style=\"color:blue;\">Not<\/span> IsDate(varDatum) Then\r\n        Err.Raise 13, \"SqlDatum\", \"Der &uuml;bergebene Wert ist kein g&uuml;ltiges Datum.\"\r\n    <span style=\"color:blue;\">Else<\/span>If blnMitZeit Then\r\n        SqlDatum = Format$(CDate(varDatum), \"\\#yyyy\\-mm\\-dd hh\\:nn\\:ss\\#\")\r\n    <span style=\"color:blue;\">Else<\/span>\r\n        SqlDatum = Format$(CDate(varDatum), \"\\#yyyy\\-mm\\-dd\\#\")\r\n    <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: SqlDatum liefert ein Datum in der von Access erwarteten Schreibweise<\/span><\/b><\/p>\n<p>Die Funktion erzeugt das ISO-Format mit Jahr, Monat und Tag, das Access unabh&auml;ngig von den L&auml;ndereinstellungen richtig auswertet. Die umgekehrten Schr&auml;gstriche im Formatausdruck sorgen daf&uuml;r, dass Raute, Bindestrich und Doppelpunkt als Zeichen ausgegeben und nicht als Formatanweisung gedeutet werden. Beim Doppelpunkt ist das zwingend, denn ohne Maskierung setzt VBA dort das landestypische Zeitzeichen ein.<\/p>\n<p>Die Pr&uuml;fung mit <b>IsDate<\/b> weist ungeeignete Werte bereits in der Hilfsfunktion mit einer verst&auml;ndlichen Fehlermeldung zur&uuml;ck. Ohne sie liefe eine versehentlich &uuml;bergebene Zeichenkette entweder in einen Fehler bei <b>CDate<\/b> oder in einen SQL-Ausdruck, dessen Ursache sich sp&auml;ter nur m&uuml;hsam zur&uuml;ckverfolgen l&auml;sst.<\/p>\n<p>Ein <b>Null<\/b>-Wert wird zum SQL-Schl&uuml;sselwort <b>Null<\/b>. Das ist bei Wertzuweisungen verwendbar, etwa in einer Aktualisierungsabfrage. In Vergleichsbedingungen muss ein Nullwert dagegen mit <b>Is Null<\/b> beziehungsweise <b>Is Not Null<\/b> gepr&uuml;ft werden &#8211; ein <b>WHERE Lieferdatum = Null<\/b> liefert grunds&auml;tzlich keine Treffer.<\/p>\n<pre><span style=\"color:blue;\">Debug.Print<\/span> SqlDatum(#4\/5\/2026#)\r\n<span style=\"color:blue;\">Debug.Print<\/span> SqlDatum(#4\/5\/2026 9:37:12 AM#, <span style=\"color:blue;\">True<\/span>)\r\n<span style=\"color:blue;\">Debug.Print<\/span> SqlDatum(Null)\r\n#2026-04-05#\r\n#2026-04-05 09:37:12#\r\nNull<\/pre>\n<p>Damit l&auml;sst sich der Tagesbereich aus der obigen Abfrage sauber zusammensetzen:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>Tagesbereich()\r\n    <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n    <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n    <span style=\"color:blue;\">Dim <\/span>strSQL<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>datTag<span style=\"color:blue;\"> As Date<\/span>\r\n    \r\n    datTag = #4\/5\/2026#\r\n    strSQL = \"SELECT * FROM tblAuftraege WHERE Erfasst &gt;= \" _\r\n        & SqlDatum(datTag) & \" AND Erfasst &lt; \" _\r\n        & SqlDatum(datTag + 1)    \r\n    <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n    <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(strSQL, dbOpenDynaset)\r\n    <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rst.EOF\r\n        <span style=\"color:blue;\">Debug.Print<\/span> rst.Fields(0), rst.Fields(1)\r\n        rst.Move<span style=\"color:blue;\">Next<\/span>\r\n    <span style=\"color:blue;\">Loop<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Noch robuster sind parametrisierte Abfragen. Dabei &uuml;bergibt DAO den Datumswert typisiert, sodass weder das regionale Format noch die Schreibweise des Datumsliterals eine Rolle spielt. Folgendes Listing zeigt, wie das aussieht:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>TagesbereichParametrisiert()\r\n    <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n    <span style=\"color:blue;\">Dim <\/span>qdf<span style=\"color:blue;\"> As <\/span>DAO.QueryDef\r\n    <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n    <span style=\"color:blue;\">Dim <\/span>datTag<span style=\"color:blue;\"> As Date<\/span>\r\n    \r\n    datTag = #4\/5\/2026#\r\n    <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n    <span style=\"color:blue;\">Set<\/span> qdf = db.CreateQueryDef(\"\", _\r\n        \"PARAMETERS pVon DateTime, pBis DateTime; \" & _\r\n        \"SELECT * FROM tblAuftraege \" & _\r\n        \"WHERE Erfasst &gt;= pVon AND Erfasst &lt; pBis\")\r\n    \r\n    qdf.Parameters(\"pVon\") = datTag\r\n    qdf.Parameters(\"pBis\") = DateAdd(\"d\", 1, datTag)\r\n    \r\n    <span style=\"color:blue;\">Set<\/span> rst = qdf.OpenRecordset\r\n    <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rst.EOF\r\n        <span style=\"color:blue;\">Debug.Print<\/span> rst.Fields(0), rst.Fields(1)\r\n        rst.Move<span style=\"color:blue;\">Next<\/span>\r\n    <span style=\"color:blue;\">Loop<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Der leere Name im Aufruf von <b>CreateQueryDef<\/b> erzeugt eine tempor&auml;re Abfrage, die nicht im Navigationsbereich erscheint. Die beiden Parameter werden mit <b>DateTime<\/b> deklariert und anschlie&szlig;end als echte Datumswerte zugewiesen &#8211; eine Zeichenkette entsteht dabei an keiner Stelle.<\/p>\n<h2>Die Kalenderwoche nach ISO 8601<\/h2>\n<p>Die eingebaute Funktion <b>DatePart<\/b> kennt das Intervall <b>ww<\/b> und liefert damit eine Kalenderwoche. &Uuml;bergeben Sie zus&auml;tzlich die Parameter <b>vbMonday<\/b> und <b>vbFirstFourDays<\/b>, entspricht die Wochennummer der Z&auml;hlung nach ISO 8601. Beide Angaben sind Pflicht: Ohne sie beginnt die Woche am Sonntag und die erste Woche des Jahres mit dem 1. Januar &#8211; das ist die amerikanische Z&auml;hlung und f&uuml;r deutsche Auswertungen unbrauchbar.<\/p>\n<p>Was <b>DatePart<\/b> dagegen nicht liefert, ist das Wochenjahr. Und genau daran scheitern Auswertungen, wie Listing 6 zeigt.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>KalenderwocheFalle()\r\n    <span style=\"color:blue;\">Debug.Print<\/span> Year(#12\/31\/2007#) & \"-KW\" _\r\n        & DatePart(\"ww\", #12\/31\/2007#, _\r\n        vbMonday, vbFirstFourDays)\r\n    <span style=\"color:blue;\">Debug.Print<\/span> Year(#1\/1\/2021#) & \"-KW\" _\r\n        & DatePart(\"ww\", #1\/1\/2021#, _\r\n        vbMonday, vbFirstFourDays)\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Hier ist das Ergebnis der Prozedur:<\/p>\n<pre>2007-KW1\r\n2021-KW53<\/pre>\n<p>Beide Angaben sind falsch. Der 31. Dezember 2007 geh&ouml;rt zur Woche 1 des Jahres <b>2008<\/b>, der 1. Januar 2021 zur Woche 53 des Jahres <b>2020<\/b>. Die Wochennummern stimmen also &#8211; nur das Jahr passt nicht dazu, weil <b>Year<\/b> das Kalenderjahr liefert und nicht das Wochenjahr. Ein Jahr 2021 mit einer Woche 53 gibt es &uuml;berhaupt nicht.<\/p>\n<p>In der Praxis f&auml;llt das erst auf, wenn eine Auswertung &uuml;ber den Jahreswechsel l&auml;uft. Eine Gruppierung nach Jahr und Woche erzeugt dann Gruppen, die es nicht gibt, und verteilt die Datens&auml;tze einer einzigen Woche auf zwei Zeilen.<\/p>\n<p>Die Norm l&ouml;st das &uuml;ber eine einfache Regel: Eine Woche geh&ouml;rt zu dem Jahr, in dem ihr Donnerstag liegt. Damit lassen sich Wochennummer und Wochenjahr aus derselben Rechnung ableiten. Die Funktion <b>IsoKalenderwoche<\/b> aus Listing 3 &uuml;bernimmt den ersten Teil.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>IsoKalenderwoche(ByVal datDatum<span style=\"color:blue;\"> As Date<\/span>)<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>datDonnerstag<span style=\"color:blue;\"> As Date<\/span>\r\n    ' Donnerstag derselben Woche ermitteln\r\n    datDonnerstag = DateValue(datDatum) - Weekday(datDatum, vbMonday) + 4\r\n    IsoKalenderwoche = Int((datDonnerstag - DateSerial(Year(datDonnerstag), 1, 1)) \/ 7) + 1\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: IsoKalenderwoche liefert die Wochennummer nach ISO 8601<\/span><\/b><\/p>\n<p>Die Funktion ermittelt zuerst den Donnerstag der Woche, in der das &uuml;bergebene Datum liegt. <b>Weekday<\/b> mit dem Parameter <b>vbMonday<\/b> liefert f&uuml;r Montag die 1, f&uuml;r Sonntag die 7; die Rechnung <b>Datum minus Wochentag plus 4<\/b> landet damit immer auf dem Donnerstag. Der Aufruf von <b>DateValue<\/b> entfernt einen etwaigen Zeitanteil, der f&uuml;r die Kalenderwoche ohne Bedeutung ist. Anschlie&szlig;end ermittelt sie die Position dieses Donnerstags innerhalb des Jahres, teilt durch sieben und addiert eins.<\/p>\n<p>Das Wochenjahr f&auml;llt dabei nebenbei ab: Es ist schlicht das Jahr des Donnerstags. Die Funktion <b>IsoKalenderjahr<\/b> aus Listing 4 gibt es zur&uuml;ck.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>IsoKalenderjahr(ByVal datDatum<span style=\"color:blue;\"> As Date<\/span>)<span style=\"color:blue;\"> As Long<\/span>\r\n    IsoKalenderjahr = Year(DateValue(datDatum) - Weekday(datDatum, vbMonday) + 4)\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 3: IsoKalenderjahr liefert das Jahr, zu dem die Woche geh&ouml;rt<\/span><\/b><\/p>\n<p>F&uuml;r die beiden Problemf&auml;lle von oben sieht das nun so aus:<\/p>\n<pre><span style=\"color:blue;\">Debug.Print<\/span> IsoKalenderjahr(#12\/31\/2007#) & \"-KW\" _\r\n    & IsoKalenderwoche(#12\/31\/2007#)\r\n<span style=\"color:blue;\">Debug.Print<\/span> IsoKalenderjahr(#1\/1\/2021#) & \"-KW\" _\r\n    & IsoKalenderwoche(#1\/1\/2021#)\r\n<span style=\"color:blue;\">Debug.Print<\/span> IsoKalenderjahr(#1\/3\/2016#) & \"-KW\" _\r\n    & IsoKalenderwoche(#1\/3\/2016#)<\/pre>\n<p>Die Ergebnisse lauten nun:<\/p>\n<pre>2008-KW1\r\n2020-KW53\r\n2015-KW53<\/pre>\n<p>Wenn Sie nach Kalenderwochen gruppieren, verwenden Sie immer beide Funktionen zusammen. Eine Auswertung, die nur nach der Wochennummer gruppiert, wirft die Woche 53 aus 2015 und die Woche 53 aus 2020 in denselben Topf.<\/p>\n<h2>Das Alter berechnen<\/h2>\n<p>Auch hier f&uuml;hrt die naheliegende L&ouml;sung in die Irre. <b>DateDiff<\/b> mit dem Intervall <b>yyyy<\/b> z&auml;hlt die Jahreswechsel zwischen zwei Datumsangaben, nicht die erreichten Geburtstage. F&uuml;r eine am 15. Juni 1980 geborene Person liefert es am 14. Juni 2026 bereits 46 statt 45. Die Funktion <b>Alter<\/b> aus Listing 5 korrigiert das.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>Alter(ByVal datGeburt<span style=\"color:blue;\"> As Date<\/span>, <span style=\"color:blue;\">Optional<\/span> ByVal datStichtag<span style=\"color:blue;\"> As Date<\/span>)<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>datGeburtstag<span style=\"color:blue;\"> As Date<\/span>\r\n    <span style=\"color:blue;\">If <\/span>datStichtag = 0<span style=\"color:blue;\"> Then<\/span> datStichtag = Date\r\n    <span style=\"color:blue;\">If <\/span>datGeburt &gt; datStichtag<span style=\"color:blue;\"> Then<\/span>\r\n        Err.Raise 5, \"Alter\", \"Das Geburtsdatum liegt nach dem Stichtag.\"\r\n    <span style=\"color:blue;\">End If<\/span>\r\n    Alter = DateDiff(\"yyyy\", datGeburt, datStichtag)\r\n    ' Geburtstag im Stichjahr\r\n    datGeburtstag = DateSerial(Year(datStichtag), Month(datGeburt), Day(datGeburt))\r\n    <span style=\"color:blue;\">If <\/span>datGeburtstag &gt; datStichtag<span style=\"color:blue;\"> Then<\/span>\r\n        Alter = Alter - 1\r\n    <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 4: Alter berechnet das vollendete Lebensalter zu einem Stichtag<\/span><\/b><\/p>\n<p>Die Funktion nimmt zun&auml;chst die Differenz der Jahreszahlen und zieht eine Eins ab, falls der Geburtstag im Stichjahr noch bevorsteht. Ein Geburtsdatum nach dem Stichtag weist sie mit einem Fehler zur&uuml;ck, weil ein negatives Alter kein sinnvolles Ergebnis w&auml;re.<\/p>\n<p>Der Stichtag ist optional; bleibt er leer, enth&auml;lt <b>datStichtag<\/b> den Wert 0, und die Funktion setzt das heutige Datum ein. Diese verbreitete Konstruktion hat einen kleinen Haken: Der 30. Dezember 1899 besitzt ebenfalls den internen Wert 0 und l&auml;sst sich deshalb nicht als Stichtag &uuml;bergeben. F&uuml;r Gesch&auml;ftsanwendungen ist das ohne Belang; wollen Sie ganz sichergehen, deklarieren Sie den Parameter als <b>Variant<\/b> und pr&uuml;fen ihn mit <b>IsMissing<\/b>.<\/p>\n<p>Der Schaltjahrfall ist bereits erledigt, ohne dass es daf&uuml;r eine eigene Zeile br&auml;uchte. F&uuml;r einen am 29. Februar Geborenen erzeugt <b>DateSerial<\/b> in einem Nicht-Schaltjahr den 1. M&auml;rz, weil die Funktion ung&uuml;ltige Tageswerte in den Folgemonat weiterrechnet. Damit wird das h&ouml;here Lebensalter in einem Nicht-Schaltjahr ab dem 1. M&auml;rz zur&uuml;ckgegeben. Das entspricht der gesetzlichen Fristberechnung nach Paragraf 188 Absatz 3 BGB, nach der das vorherige Lebensjahr mit Ablauf des 28. Februar endet.<\/p>\n<pre><span style=\"color:blue;\">Debug.Print<\/span> Alter(#6\/15\/1980#, #6\/14\/2026#)\r\n<span style=\"color:blue;\">Debug.Print<\/span> Alter(#6\/15\/1980#, #6\/15\/2026#)\r\n<span style=\"color:blue;\">Debug.Print<\/span> Alter(#2\/29\/2000#, #2\/28\/2026#)\r\n<span style=\"color:blue;\">Debug.Print<\/span> Alter(#2\/29\/2000#, #3\/1\/2026#)<\/pre>\n<p>Hier sind die Ergebnisse dieser Aufrufe:<\/p>\n<pre>45\r\n46\r\n25\r\n26<\/pre>\n<h2>Monats- und Quartalsgrenzen<\/h2>\n<p>Den ersten Tag eines Monats liefert <b>DateSerial<\/b> unmittelbar. F&uuml;r den letzten gibt es einen Kniff, den Listing 6 in den beiden Funktionen <b>MonatsErster<\/b> und <b>MonatsLetzter<\/b> ausnutzt.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>MonatsErster(ByVal datDatum<span style=\"color:blue;\"> As Date<\/span>)<span style=\"color:blue;\"> As Date<\/span>\r\n    MonatsErster = DateSerial(Year(datDatum), Month(datDatum), 1)\r\n<span style=\"color:blue;\">End Function<\/span>\r\n<span style=\"color:blue;\">Public Function <\/span>MonatsLetzter(ByVal datDatum<span style=\"color:blue;\"> As Date<\/span>)<span style=\"color:blue;\"> As Date<\/span>\r\n    MonatsLetzter = DateSerial(Year(datDatum), Month(datDatum) + 1, 0)\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 5: MonatsErster und MonatsLetzter ermitteln die Monatsgrenzen<\/span><\/b><\/p>\n<p><b>MonatsLetzter<\/b> &uuml;bergibt an <b>DateSerial<\/b> den Folgemonat und als Tag die Null. Da <b>DateSerial<\/b> Werte au&szlig;erhalb des g&uuml;ltigen Bereichs weiterrechnet, ist der nullte Tag des Folgemonats genau der letzte Tag des gew&uuml;nschten Monats. Der Kniff k&uuml;mmert sich damit ganz nebenbei um unterschiedlich lange Monate und um Schaltjahre. Auch der Dezember ist kein Sonderfall: Der dreizehnte Monat eines Jahres ist der Januar des Folgejahres. Anbei einige Beispielaufrufe:<\/p>\n<pre><span style=\"color:blue;\">Debug.Print<\/span> MonatsLetzter(#4\/5\/2026#)\r\n<span style=\"color:blue;\">Debug.Print<\/span> MonatsLetzter(#2\/5\/2026#)\r\n<span style=\"color:blue;\">Debug.Print<\/span> MonatsLetzter(#2\/5\/2024#)\r\n<span style=\"color:blue;\">Debug.Print<\/span> MonatsLetzter(#12\/5\/2026#)<\/pre>\n<p>Diese liefern die folgenden Ergebnisse:<\/p>\n<pre>30.04.2026\r\n28.02.2026\r\n29.02.2024\r\n31.12.2026<\/pre>\n<p>Nach demselben Muster arbeiten die drei Funktionen f&uuml;r das Quartal in Listing 7:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>Quartal(ByVal datDatum<span style=\"color:blue;\"> As Date<\/span>)<span style=\"color:blue;\"> As Long<\/span>\r\n    Quartal = Int((Month(datDatum) - 1) \/ 3) + 1\r\n<span style=\"color:blue;\">End Function<\/span>\r\n<span style=\"color:blue;\">Public Function <\/span>QuartalsErster(ByVal datDatum<span style=\"color:blue;\"> As Date<\/span>)<span style=\"color:blue;\"> As Date<\/span>\r\n    QuartalsErster = DateSerial(Year(datDatum), (Quartal(datDatum) - 1) * 3 + 1, 1)\r\n<span style=\"color:blue;\">End Function<\/span>\r\n<span style=\"color:blue;\">Public Function <\/span>QuartalsLetzter(ByVal datDatum<span style=\"color:blue;\"> As Date<\/span>)<span style=\"color:blue;\"> As Date<\/span>\r\n    QuartalsLetzter = DateSerial(Year(datDatum), Quartal(datDatum) * 3 + 1, 0)\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 6: Quartal, QuartalsErster und QuartalsLetzter f&uuml;r Quartalsauswertungen<\/span><\/b><\/p>\n<pre><span style=\"color:blue;\">Debug.Print<\/span> Quartal(#4\/5\/2026#)\r\n<span style=\"color:blue;\">Debug.Print<\/span> QuartalsErster(#4\/5\/2026#)\r\n<span style=\"color:blue;\">Debug.Print<\/span> QuartalsLetzter(#4\/5\/2026#)<\/pre>\n<p>Hier sind die Ergebnisse der Beispielaufrufe:<\/p>\n<pre>2\r\n01.04.2026\r\n30.06.2026<\/pre>\n<p>Beim Rechnen mit ganzen Monaten lauert eine Falle, die man kennen sollte: <b>DateAdd<\/b> ist nicht umkehrbar. Der Aufruf <b>DateAdd(&#8222;m&#8220;, 1, #1\/31\/2026#)<\/b> liefert den 28. Februar, weil es keinen 31. Februar gibt. Ein anschlie&szlig;endes <b>DateAdd(&#8222;m&#8220;, -1, &#8230;)<\/b> f&uuml;hrt dann auf den 28. Januar und nicht zur&uuml;ck auf den Ausgangswert. Bei Ratenpl&auml;nen und F&auml;lligkeiten ist es deshalb sicherer, immer vom urspr&uuml;nglichen Datum aus zu rechnen statt schrittweise weiterzuz&auml;hlen.<\/p>\n<h2>Zeitspannen &uuml;ber Mitternacht<\/h2>\n<p>Eine Schicht von 22:00 bis 06:00 ergibt bei schlichter Subtraktion einen negativen Wert. Die Funktion <b>Zeitspanne<\/b> aus Listing 8 f&auml;ngt das ab, indem sie dem Endzeitpunkt einen Tag hinzuf&uuml;gt, wenn er vor dem Beginn liegt. Die Funktion demonstrieren die folgenden Aufrufe:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>Zeitspanne(ByVal datVon<span style=\"color:blue;\"> As Date<\/span>, ByVal datBis<span style=\"color:blue;\"> As Date<\/span>)<span style=\"color:blue;\"> As Double<\/span>\r\n    <span style=\"color:blue;\">If <\/span>datBis &lt; datVon<span style=\"color:blue;\"> Then<\/span> datBis = datBis + 1\r\n    Zeitspanne = (datBis - datVon) * 24\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 7: Zeitspanne liefert die Stunden zwischen zwei Uhrzeiten<\/span><\/b><\/p>\n<pre><span style=\"color:blue;\">Debug.Print<\/span> Zeitspanne(#10:00:00 PM#, #6:00:00 AM#)\r\n<span style=\"color:blue;\">Debug.Print<\/span> Zeitspanne(#8:00:00 AM#, #4:30:00 PM#)<\/pre>\n<p>Hier die Resultate:<\/p>\n<pre>8\r\n8,5<\/pre>\n<p>Die Funktion setzt voraus, dass eine Schicht k&uuml;rzer als 24 Stunden ist &#8211; f&uuml;r Arbeitszeiten eine unproblematische Annahme. Sind die Datumswerte vollst&auml;ndig, also mit Tag und Uhrzeit gespeichert, brauchen Sie die Korrektur nicht und k&ouml;nnen unmittelbar subtrahieren. Vollst&auml;ndige Datumswerte beseitigen allerdings nur die Unklarheit beim &Uuml;berschreiten von Mitternacht.<\/p>\n<p>Eine Einschr&auml;nkung geh&ouml;rt allerdings dazu: Die Funktion rechnet mit reinen Uhrzeiten und kennt weder Datum noch Zeitzone. In N&auml;chten mit einer Zeitumstellung kann die tats&auml;chlich vergangene Zeit deshalb um eine Stunde abweichen &#8211; eine Schicht von 22:00 bis 06:00 dauert dann sieben oder neun Stunden, die Funktion meldet aber weiterhin acht. Das gilt genauso f&uuml;r vollst&auml;ndige Datumswerte, solange es sich um lokale Zeitangaben handelt. Soll die tats&auml;chlich vergangene Zeit bestimmt werden, f&uuml;hrt der zuverl&auml;ssigste Weg &uuml;ber UTC-Werte, weil dort keine Zeitumstellung dazwischenkommt.<\/p>\n<h2>Stunden jenseits von 24 ausgeben<\/h2>\n<p>Beim Ausgeben summierter Zeiten entt&auml;uscht <b>Format<\/b> mit dem Ausdruck <b>&#8222;hh:nn&#8220;<\/b>: Sobald die Summe 24 Stunden &uuml;berschreitet, beginnt die Anzeige wieder bei null, weil ein Datumswert einen Tag weiterz&auml;hlt. F&uuml;r Wochen- oder Monatssummen brauchen Sie deshalb eine eigene Formatierung, wie sie die Funktion <b>StundenFormat<\/b> in Listing 9 vornimmt.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>StundenFormat(ByVal dblStunden<span style=\"color:blue;\"> As Double<\/span>)<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>lngGesamtminuten<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>lngStunden<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>lngMinuten<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">If <\/span>dblStunden &lt; 0<span style=\"color:blue;\"> Then<\/span>\r\n        Err.Raise 5, \"StundenFormat\", \"Negative Zeitspannen werden nicht unterst&uuml;tzt.\"\r\n    <span style=\"color:blue;\">End If<\/span>\r\n    ' Kaufmaennisch auf volle Minuten runden\r\n    lngGesamtminuten = Fix(dblStunden * 60 + 0.5)\r\n    lngStunden = lngGesamtminuten \\ 60\r\n    lngMinuten = lngGesamtminuten <span style=\"color:blue;\">Mod<\/span> 60\r\n    StundenFormat = Format$(lngStunden, \"00\") & \":\" & Format$(lngMinuten, \"00\")\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 8: StundenFormat gibt auch Summen &uuml;ber 24 Stunden korrekt aus<\/span><\/b><\/p>\n<pre><span style=\"color:blue;\">Debug.Print<\/span> StundenFormat(7.5)\r\n<span style=\"color:blue;\">Debug.Print<\/span> StundenFormat(41.25)\r\n<span style=\"color:blue;\">Debug.Print<\/span> StundenFormat(0.75)\r\n07:30\r\n41:15\r\n00:45<\/pre>\n<p>Die Funktion rechnet bewusst &uuml;ber die Gesamtzahl der Minuten. Der Zuschlag von 0,5 vor dem Abschneiden mit <b>Fix<\/b> rundet kaufm&auml;nnisch &#8211; anders als <b>CLng<\/b>, das bei genau einem halben Wert zur n&auml;chsten geraden Zahl rundet und aus 30,5 Minuten deshalb 30 statt 31 machen w&uuml;rde. Ganzzahldivision und <b>Mod<\/b> zerlegen das Ergebnis danach in Stunden und Minuten, sodass sich ein Sonderfall f&uuml;r volle 60 Minuten er&uuml;brigt.<\/p>\n<p>Die Pr&uuml;fung auf einen negativen Wert am Anfang ist n&ouml;tig, weil die Rundung mit dem Zuschlag nur f&uuml;r positive Werte in die erwartete Richtung geht. Brauchen Sie auch negative Salden, etwa f&uuml;r ein Gleitzeitkonto, trennen Sie das Vorzeichen ab, formatieren den Betrag und stellen das Minuszeichen anschlie&szlig;end wieder voran. Warum &uuml;berhaupt gerundet werden muss, zeigt ein Blick in den Direktbereich:<\/p>\n<pre><span style=\"color:blue;\">Debug.Print<\/span> (#8:00:00 AM# - #7:00:00 AM#) * 24\r\n0,999999999999999<\/pre>\n<p>Eine Stunde ist als Zahl der Wert 1\/24, und dieser Bruch l&auml;sst sich bin&auml;r nicht exakt darstellen. Bei einer einzelnen Differenz f&auml;llt das nicht auf, bei einer Summe &uuml;ber hundert Datens&auml;tze durchaus. Vergleichen Sie berechnete Zeitspannen deshalb nicht ungepr&uuml;ft mit dem Gleichheitszeichen, sondern runden Sie sie zuvor oder arbeiten Sie mit einem Toleranzbereich:<\/p>\n<pre><span style=\"color:blue;\">If <\/span>Abs(dblStunden - 8) &lt; 0.000001<span style=\"color:blue;\"> Then<\/span><\/pre>\n<p>F&uuml;r zwei unver&auml;ndert gespeicherte Datumswerte ist ein Vergleich mit dem Gleichheitszeichen dagegen unbedenklich &#8211; das Problem entsteht erst durch das Rechnen. Wenn Sie Arbeitszeiten dauerhaft speichern, legen Sie sie besser als Anzahl der Minuten in einem <b>Long<\/b>-Feld ab statt als Datumswert.<\/p>\n<h2>Ortszeit und UTC<\/h2>\n<p>F&uuml;r Schnittstellen, Protokolle und Zeitstempel in Datenbanken mit Anwendern in mehreren Zeitzonen brauchen Sie die koordinierte Weltzeit. VBA bringt daf&uuml;r nichts mit, Windows dagegen schon. Die Funktion <b>UtcJetzt<\/b> in Listing 10 holt sie &uuml;ber die API-Funktion <b>GetSystemTime<\/b>.<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>Type SYSTEMTIME\r\n    wYear<span style=\"color:blue;\"> As Integer<\/span>\r\n    wMonth<span style=\"color:blue;\"> As Integer<\/span>\r\n    wDayOfWeek<span style=\"color:blue;\"> As Integer<\/span>\r\n    wDay<span style=\"color:blue;\"> As Integer<\/span>\r\n    wHour<span style=\"color:blue;\"> As Integer<\/span>\r\n    wMinute<span style=\"color:blue;\"> As Integer<\/span>\r\n    wSecond<span style=\"color:blue;\"> As Integer<\/span>\r\n    wMilliseconds<span style=\"color:blue;\"> As Integer<\/span>\r\nEnd Type\r\n#If VBA7 Then\r\n    <span style=\"color:blue;\">Private <\/span>Declare PtrSafe Sub GetSystemTime Lib \"kernel32\" (ByRef lpSystemTime<span style=\"color:blue;\"> As <\/span>SYSTEMTIME)\r\n#Else\r\n    <span style=\"color:blue;\">Private <\/span>Declare Sub GetSystemTime Lib \"kernel32\" (ByRef lpSystemTime<span style=\"color:blue;\"> As <\/span>SYSTEMTIME)\r\n#End If\r\n<span style=\"color:blue;\">Public Function <\/span>UtcJetzt()<span style=\"color:blue;\"> As Date<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>typZeit<span style=\"color:blue;\"> As <\/span>SYSTEMTIME\r\n    GetSystemTime typZeit\r\n    UtcJetzt = DateSerial(typZeit.wYear, typZeit.wMonth, typZeit.wDay) + TimeSerial(typZeit.wHour, typZeit.wMinute, _\r\n        typZeit.wSecond)\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 9: UtcJetzt liefert die aktuelle Weltzeit<\/span><\/b><\/p>\n<p>Die API-Funktion f&uuml;llt eine Struktur vom Typ <b>SYSTEMTIME<\/b> mit den Bestandteilen der aktuellen Weltzeit. Aus deren Feldern setzen <b>DateSerial<\/b> und <b>TimeSerial<\/b> einen Datumswert zusammen. Die bedingte Kompilierung mit <b>#If VBA7<\/b> sorgt daf&uuml;r, dass die Deklaration sowohl in der 32-Bit- als auch in der 64-Bit-Version von Access funktioniert.<\/p>\n<p>Ein VBA-Datumswert besitzt keine Zeitzonenkennung. Der R&uuml;ckgabewert von <b>UtcJetzt<\/b> muss deshalb durch Benennung und Dokumentation eindeutig als UTC-Wert gekennzeichnet bleiben &#8211; ein Feldname wie <b>ErfasstUtc<\/b> ist hier keine Pedanterie. Wird der Wert sp&auml;ter wie eine Ortszeit behandelt, entsteht eine Verschiebung, die niemandem auff&auml;llt.<\/p>\n<p>Den Versatz zur Ortszeit erhalten Sie durch die Differenz zur Funktion <b>Now<\/b>. Die Rundung auf zwei Nachkommastellen f&auml;ngt dabei die Sekunden ab, die zwischen den beiden Aufrufen vergehen:<\/p>\n<pre><span style=\"color:blue;\">Debug.Print<\/span> UtcJetzt()\r\n<span style=\"color:blue;\">Debug.Print<\/span> Now()\r\n<span style=\"color:blue;\">Debug.Print<\/span> Round((Now() - UtcJetzt()) * 24, 2)\r\n05.04.2026 08:37:12\r\n05.04.2026 10:37:12\r\n2<\/pre>\n<p>Dieser Ausdruck liefert ausschlie&szlig;lich den momentan geltenden Versatz, in Deutschland also zwei Stunden w&auml;hrend der Sommerzeit und eine Stunde im Winter. F&uuml;r historische oder zuk&uuml;nftige Zeitpunkte ben&ouml;tigen Sie eine zeitzonenf&auml;hige Umrechnung, welche die zum jeweiligen Datum g&uuml;ltigen Sommerzeitregeln ber&uuml;cksichtigt &#8211; ein per Hand berechneter Versatz f&uuml;hrt dort zuverl&auml;ssig in die Irre.<\/p>\n<h2>Zusammenfassung<\/h2>\n<p>Fast alle &Uuml;berraschungen beim Rechnen mit Datum und Zeit lassen sich auf zwei Ursachen zur&uuml;ckf&uuml;hren. Die erste ist der unsichtbare Zeitanteil, der Vergleiche auf Gleichheit scheitern l&auml;sst &#8211; dagegen hilft ein Bereich von einem Tag bis zum n&auml;chsten, wie ihn Listing 3 zeigt. Die zweite ist die Flie&szlig;kommadarstellung, aus der die Rundungsfehler bei berechneten Zeitspannen folgen.<\/p>\n<p>Die &uuml;brigen Funktionen dieses Beitrags nehmen Ihnen jeweils eine konkrete Falle ab: <b>SqlDatum<\/b> das Datumsformat in Abfragen, <b>IsoKalenderwoche<\/b> und <b>IsoKalenderjahr<\/b> den Jahreswechsel, <b>Alter<\/b> den noch nicht erreichten Geburtstag, <b>MonatsLetzter<\/b> die unterschiedlich langen Monate und <b>StundenFormat<\/b> aus die Grenze bei 24 Stunden.<\/p>\n<p>Funktionen, die Sie in Abfragen verwenden, sollten deshalb Parameter vom Typ <b>Variant<\/b> annehmen und den Nullwert selbst behandeln. Ein zus&auml;tzliches <b>Is Not Null<\/b> in der WHERE-Klausel ist sinnvoll, ersetzt diese Pr&uuml;fung aber nicht zuverl&auml;ssig &#8211; Access garantiert die Reihenfolge nicht, in der es die Bedingungen auswertet, sodass die Funktion trotzdem mit <b>Null<\/b> aufgerufen werden kann.<\/p>\n<p>Kopieren Sie sich die Funktionen in ein Standardmodul, dann haben Sie sie in jedem Projekt zur Hand. In Abfragen lassen sie sich ebenfalls einsetzen, allerdings mit einer Einschr&auml;nkung: Ein Nullwert l&auml;sst sich nicht an einen Parameter vom Typ <b>Date<\/b> &uuml;bergeben.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Datumsberechnungen wirken harmlos, bis die Abfrage die Datens&auml;tze von heute nicht findet, die Kalenderwoche zum Jahreswechsel danebenliegt oder die Summe der Arbeitszeiten pl&ouml;tzlich 07:59 statt 08:00 lautet. Alle drei F&auml;lle haben dieselbe Ursache: Access speichert Datum und Uhrzeit anders, als die angezeigte Darstellung vermuten l&auml;sst. Dieser Beitrag zeigt, was dabei schiefgehen kann, und liefert die Funktionen, die Ihnen die &uuml;blichen Fallen abnehmen.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[662026,66052026,44000025],"tags":[],"class_list":["post-55001620","post","type-post","status-publish","format-standard","hentry","category-662026","category-66052026","category-VBA_und_Programmiertechniken"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.9 (Yoast SEO v28.4) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Rechnen mit Datum und Zeit ohne &Uuml;berraschungen - Access im Unternehmen<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/access-im-unternehmen.de\/Rechnen_mit_Datum_und_Zeit_ohne_Ueberraschungen\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Rechnen mit Datum und Zeit ohne &Uuml;berraschungen\" \/>\n<meta property=\"og:description\" content=\"Datumsberechnungen wirken harmlos, bis die Abfrage die Datens&auml;tze von heute nicht findet, die Kalenderwoche zum Jahreswechsel danebenliegt oder die Summe der Arbeitszeiten pl&ouml;tzlich 07:59 statt 08:00 lautet. Alle drei F&auml;lle haben dieselbe Ursache: Access speichert Datum und Uhrzeit anders, als die angezeigte Darstellung vermuten l&auml;sst. Dieser Beitrag zeigt, was dabei schiefgehen kann, und liefert die Funktionen, die Ihnen die &uuml;blichen Fallen abnehmen.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/Rechnen_mit_Datum_und_Zeit_ohne_Ueberraschungen\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2026-09-08T11:29:01+00:00\" \/>\n<meta name=\"author\" content=\"Andr\u00e9 Minhorst\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Andr\u00e9 Minhorst\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"17\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Rechnen_mit_Datum_und_Zeit_ohne_Ueberraschungen\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Rechnen_mit_Datum_und_Zeit_ohne_Ueberraschungen\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"Rechnen mit Datum und Zeit ohne &Uuml;berraschungen\",\"datePublished\":\"2026-09-08T11:29:01+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Rechnen_mit_Datum_und_Zeit_ohne_Ueberraschungen\\\/\"},\"wordCount\":2605,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"articleSection\":[\"2026\",\"5\\\/2026\",\"VBA und Programmiertechniken\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Rechnen_mit_Datum_und_Zeit_ohne_Ueberraschungen\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Rechnen_mit_Datum_und_Zeit_ohne_Ueberraschungen\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Rechnen_mit_Datum_und_Zeit_ohne_Ueberraschungen\\\/\",\"name\":\"Rechnen mit Datum und Zeit ohne &Uuml;berraschungen - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"datePublished\":\"2026-09-08T11:29:01+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Rechnen_mit_Datum_und_Zeit_ohne_Ueberraschungen\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Rechnen_mit_Datum_und_Zeit_ohne_Ueberraschungen\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Rechnen_mit_Datum_und_Zeit_ohne_Ueberraschungen\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Rechnen mit Datum und Zeit ohne &Uuml;berraschungen\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\",\"name\":\"Access im Unternehmen\",\"description\":\"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Microsoft Access\",\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/access-im-unternehmen.de\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\",\"name\":\"Andr\u00e9 Minhorst Verlag\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/wp-content\\\/uploads\\\/2019\\\/09\\\/aiu_wp.png\",\"contentUrl\":\"https:\\\/\\\/access-im-unternehmen.de\\\/wp-content\\\/uploads\\\/2019\\\/09\\\/aiu_wp.png\",\"width\":370,\"height\":111,\"caption\":\"Andr\u00e9 Minhorst Verlag\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\",\"name\":\"Andr\u00e9 Minhorst\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"caption\":\"Andr\u00e9 Minhorst\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Rechnen mit Datum und Zeit ohne &Uuml;berraschungen - Access im Unternehmen","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/access-im-unternehmen.de\/Rechnen_mit_Datum_und_Zeit_ohne_Ueberraschungen\/","og_locale":"de_DE","og_type":"article","og_title":"Rechnen mit Datum und Zeit ohne &Uuml;berraschungen","og_description":"Datumsberechnungen wirken harmlos, bis die Abfrage die Datens&auml;tze von heute nicht findet, die Kalenderwoche zum Jahreswechsel danebenliegt oder die Summe der Arbeitszeiten pl&ouml;tzlich 07:59 statt 08:00 lautet. Alle drei F&auml;lle haben dieselbe Ursache: Access speichert Datum und Uhrzeit anders, als die angezeigte Darstellung vermuten l&auml;sst. Dieser Beitrag zeigt, was dabei schiefgehen kann, und liefert die Funktionen, die Ihnen die &uuml;blichen Fallen abnehmen.","og_url":"https:\/\/access-im-unternehmen.de\/Rechnen_mit_Datum_und_Zeit_ohne_Ueberraschungen\/","og_site_name":"Access im Unternehmen","article_published_time":"2026-09-08T11:29:01+00:00","author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"17\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/Rechnen_mit_Datum_und_Zeit_ohne_Ueberraschungen\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/Rechnen_mit_Datum_und_Zeit_ohne_Ueberraschungen\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"Rechnen mit Datum und Zeit ohne &Uuml;berraschungen","datePublished":"2026-09-08T11:29:01+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Rechnen_mit_Datum_und_Zeit_ohne_Ueberraschungen\/"},"wordCount":2605,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"articleSection":["2026","5\/2026","VBA und Programmiertechniken"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/Rechnen_mit_Datum_und_Zeit_ohne_Ueberraschungen\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/Rechnen_mit_Datum_und_Zeit_ohne_Ueberraschungen\/","url":"https:\/\/access-im-unternehmen.de\/Rechnen_mit_Datum_und_Zeit_ohne_Ueberraschungen\/","name":"Rechnen mit Datum und Zeit ohne &Uuml;berraschungen - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"datePublished":"2026-09-08T11:29:01+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/Rechnen_mit_Datum_und_Zeit_ohne_Ueberraschungen\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/Rechnen_mit_Datum_und_Zeit_ohne_Ueberraschungen\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/Rechnen_mit_Datum_und_Zeit_ohne_Ueberraschungen\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"Rechnen mit Datum und Zeit ohne &Uuml;berraschungen"}]},{"@type":"WebSite","@id":"https:\/\/access-im-unternehmen.de\/#website","url":"https:\/\/access-im-unternehmen.de\/","name":"Access im Unternehmen","description":"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Microsoft Access","publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/access-im-unternehmen.de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Organization","@id":"https:\/\/access-im-unternehmen.de\/#organization","name":"Andr\u00e9 Minhorst Verlag","url":"https:\/\/access-im-unternehmen.de\/","logo":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/logo\/image\/","url":"https:\/\/access-im-unternehmen.de\/wp-content\/uploads\/2019\/09\/aiu_wp.png","contentUrl":"https:\/\/access-im-unternehmen.de\/wp-content\/uploads\/2019\/09\/aiu_wp.png","width":370,"height":111,"caption":"Andr\u00e9 Minhorst Verlag"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f","name":"Andr\u00e9 Minhorst","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","caption":"Andr\u00e9 Minhorst"}}]}},"_links":{"self":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55001620","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/comments?post=55001620"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55001620\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55001620"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55001620"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55001620"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}