TL;DR — Ein Datum ist ein
Double, also istmyDate + 1morgen undmyDate - 7letzte Woche — schlichte Arithmetik stimmt für Tage. Sie fällt bei Monaten und Jahren auseinander, weil ein Monat keine 30 Tage und ein Jahr keine 365 Tage hat.DateAdd("m", 1, d)kennt den Kalender;DateDiff("d", a, b)zählt ganze Tage; undDateDiff("yyyy", a, b)zählt überschrittene Jahresgrenzen, nicht verstrichene Zeit — weshalb 31. Dez → 1. Jan „1 Jahr" ergibt.
Sub DateMathDemo()
Debug.Print #2026-01-31# + 1 ' 2026-02-01 - Tage: schlichtes + geht
Debug.Print DateAdd("m", 1, #2026-01-31#) ' 2026-02-28 - monatsbewusst, begrenzt
Debug.Print DateDiff("d", #2026-01-01#, #2026-03-01#) ' 59 - ganze Tage dazwischen
Debug.Print DateSerial(2026, 3, 0) ' 2026-02-28 - letzter Tag im Februar
End Sub
Datumsrechnung in VBA steht und fällt mit einer Tatsache: Ein Datum ist ein Double, das Tage zählt. Das
macht Tages-Mathematik trivial — + 1, - 7, Date + 30 funktionieren alle einfach, weil ein Tag
genau 1 ist. Der Ärger beginnt, wenn Sie annehmen, derselbe Trick skaliere auf Monate und Jahre, die
keine feste Länge haben. DateAdd, DateDiff und DateSerial gibt es genau dafür: den
kalenderbewussten Teil zu erledigen, den schlichtes + und - nicht können.
Was Sie lernen
- Das mentale Modell — schlichtes
+/-stimmt für Tage, ist falsch für Monate und Jahre DateAdd(interval, number, date)und die Intervallcodes, die beißen ("m"vs."n","y"vs."yyyy")- Warum
DateAdd("m", 1, 31. Jan)den 28. Feb ergibt — Monatsende-Intelligenz, die Sie mit+nicht bekommen DateDiffzählt überschrittene Grenzen, nicht verstrichene Dauer — das „1 Jahr" aus einem einzigen TagDateSerialbaut ein Datum aus Teilen ohne Locale-Mehrdeutigkeit, und die Letzter-Tag-des-Monats-Redewendung- Wann Sie schlichte Arithmetik nehmen und wann eine Funktion Pflicht ist
Das mentale Modell: Schlichte Mathematik reicht nur für Tage
Weil ein Datum ein Double aus Tagen ist, braucht Tages-Arithmetik überhaupt keine Funktion:
tomorrow = Date + 1
lastWeek = Date - 7
Debug.Print #2026-02-28# + 1 ' 2026-03-01 - VBA rollt den Monat fuer Sie um
Das ist wirklich korrekt — VBA meistert Monatsenden und Schaltjahre, wenn Sie ganze Tage addieren, weil es bloß zur Seriennummer hinzuaddiert. Der Fehler ist, einen Monat oder ein Jahr für eine Anzahl Tage zu halten:
nextMonth = Date + 30 ' FALSCH - 30 Tage sind kein Monat
nextYear = Date + 365 ' FALSCH - verpasst den Schalttag, driftet jedes Jahr
+ 30 landet je nach Monat auf verschiedenen Tagen; + 365 liegt in jeder Spanne, die den 29. Februar
enthält, um einen Tag daneben. In dem Augenblick, in dem Ihre Einheit Monat oder Jahr ist, ist
schlichte Arithmetik ein Bug, und Sie brauchen DateAdd.
DateAdd und die Intervallcodes, die beißen
DateAdd(interval, number, date) addiert number Einheiten von interval zu date. Der interval ist
ein String-Code, und zwei Kollisionen verursachen den Großteil der Verwirrung:
| Code | Einheit | Vorsicht |
|---|---|---|
"yyyy" |
Jahr | "y" ist nicht Jahr — es bedeutet Tag des Jahres |
"q" |
Quartal | |
"m" |
Monat | "m" ist Monat; Minute ist "n" |
"ww" |
Woche | |
"d" |
Tag | "y" und "w" verhalten sich auch als Tage |
"h" |
Stunde | |
"n" |
Minute | nicht "m" |
"s" |
Sekunde |
DateAdd("m", 15, startTime) ' addiert 15 MONATE - vermutlich nicht gemeint
DateAdd("n", 15, startTime) ' addiert 15 MINUTEN - das n, das Sie eigentlich wollten
Die Verwechslung "m" / "n" ist der Paradebug: Greifen Sie zu "m" in dem Glauben, es hieße „Minute",
und Sie haben klammheimlich fünfzehn Monate zu einem Zeitstempel addiert. Sprechen Sie die Codes einmal
laut aus — m ist Monat, n ist Minute, yyyy ist Jahr — und die ganze Familie hört auf,
fehleranfällig zu sein. number darf negativ sein, um zu subtrahieren, und das Ergebnis ist immer ein
richtiges Datum.
Warum DateAdd den 28. Feb ergibt, wenn Sie zum 31. Jan einen Monat addieren
Das ist der Gewinn, den schlichte Arithmetik Ihnen nie geben kann. Addieren Sie einen Monat zum 31.
Januar, gibt es keinen „31. Februar" zum Landen, also begrenzt DateAdd auf den letzten gültigen Tag
des Zielmonats:
DateAdd("m", 1, #2026-01-31#) ' 2026-02-28 (2028 ergaebe 2028-02-29)
DateAdd("m", 1, #2026-03-31#) ' 2026-04-30 (April hat 30 Tage)
DateAdd("yyyy", 1, #2028-02-29#) ' 2029-02-28 (kein Schalttag naechstes Jahr)
DateAdd weiß, wie viele Tage jeder Monat hat, und passt Schaltjahre automatisch an — genau das Wissen,
das + 30 wegwirft. Wenn Sie Fälligkeitsdaten, Verlängerungen oder „denselben Tag im nächsten Monat"
berechnen, ist dieses Begrenzen das gewünschte Verhalten und der Grund, Monatsrechnung nie von Hand zu
stricken.
DateDiff zählt überschrittene Grenzen, nicht verstrichene Zeit
DateDiff(interval, date1, date2) sieht aus wie „wie viel Zeit zwischen zwei Datumswerten", und für
"d" (Tage) ist es das auch. Für "m", "yyyy", "q" und "ww" bedeutet es etwas Subtileres und
Überraschenderes: wie viele Intervallgrenzen zwischen den beiden Datumswerten liegen, nicht wie viel
Zeit tatsächlich verstrich.
DateDiff("yyyy", #2025-12-31#, #2026-01-01#) ' 1 - eine Neujahrsgrenze, aber EINEN Tag entfernt
DateDiff("m", #2026-01-31#, #2026-02-01#) ' 1 - eine Monatsgrenze, einen Tag entfernt
DateDiff("d", #2026-01-31#, #2026-02-01#) ' 1 - ein echter Tag (dieser ist woertlich)
DateDiff("yyyy", …) ist also eine Zählung der Kalenderjahr-Wechsel, was nicht jemandes Alter und
nicht verstrichene Jahre ist. Für eine echte verstrichene Zählung berechnen Sie die Grenzdifferenz
und korrigieren dann — beim Alter ziehen Sie 1 ab, wenn der Geburtstag dieses Jahr noch nicht war:
age = DateDiff("yyyy", dob, Date)
If DateSerial(Year(Date), Month(dob), Day(dob)) > Date Then age = age - 1
DateDiff liefert außerdem eine negative Zahl, wenn date1 später als date2 ist — ein praktischer
Weg, die Reihenfolge zu testen. Die Regel: Nehmen Sie "d" bedenkenlos für ganze Tage; behandeln Sie
"m"/"yyyy"/"q" als Grenzzählungen und korrigieren Sie, bevor Sie das Ergebnis eine Dauer nennen.
DateSerial baut ein Datum aus Teilen, ohne Locale-Mehrdeutigkeit
Wenn Sie Jahr, Monat und Tag als getrennte Zahlen haben, kleben Sie sie nicht in eine Zeichenkette und
hoffen, dass CDate sie in der richtigen Reihenfolge liest — das hängt von den
Regionseinstellungen des Rechners ab und vertauscht über Grenzen hinweg klammheimlich Tag und Monat.
DateSerial(year, month, day) baut das Datum direkt, ohne Text und ohne Mehrdeutigkeit:
d = DateSerial(2026, 2, 1) ' immer der 1. Februar 2026, auf jeder Maschine
Noch besser: DateSerial normalisiert Überlauf — Monat 13 rollt ins nächste Jahr, Tag 0 ist der
letzte Tag des Vormonats. Das liefert die zwei nützlichsten Redewendungen im Datumscode:
lastDayOfMonth = DateSerial(y, m + 1, 0) ' Tag 0 = letzter Tag im Monat m
firstOfNextQ = DateSerial(y, m + 3, 1) ' drei Monate weiter, Tag 1
DateSerial(y, m + 1, 0) ist das kanonische „letzter Tag dieses Monats" — keine Nachschlagetabelle mit
Monatslängen, kein Schaltjahr-Sonderfall. Kombinieren Sie es mit Year, Month und Day aus der
Anleitung zur Teil-Extraktion, und Sie können jedes Datum relativ zu einem anderen
bauen.
Das ehrliche Fazit: Tage von Hand, alles andere per Funktion
Die Trennlinie ist klar, und auf der richtigen Seite zu bleiben beseitigt fast jeden Datumsrechnungs-Bug:
- Tage → schlichte Arithmetik →
date + n,date - n. Korrekt und schnell; VBA rollt Monate und Schaltjahre für Sie. - Monate / Jahre →
DateAdd→ nie+ 30oder+ 365.DateAdd("m", …)begrenzt auf echte Monatslängen; denken Sie daran,"m"ist Monat und"n"ist Minute. - Abstände →
DateDiff, aber lesen Sie es als Grenzen →"d"sind wörtliche Tage;"m"/"yyyy"zählen Grenzüberschreitungen, also korrigieren Sie, bevor Sie es eine Dauer nennen. - Aus Teilen bauen →
DateSerial→ keine Locale-Mehrdeutigkeit, undDateSerial(y, m + 1, 0)ist die Letzter-Tag-des-Monats-Redewendung.
Der eine Satz zum Behalten: Der +-Operator kennt den Kalender nicht, und DateDiff misst keine Zeit.
Nehmen Sie jedes für die eine Sache, in der es recht hat.
Wie ExcelMaster hilft
Die teuren Datumsrechnungs-Bugs sind die plausiblen: ein Verlängerungsdatum, als + 30 berechnet, das
über die Monatslängen driftet, ein „Alter" aus DateDiff("yyyy", …), das rund um Geburtstage ein Jahr
danebenliegt, ein Fälligkeitsdatum, aus einer Zeichenkette gebaut, das bei den Regionseinstellungen eines
Kollegen Tag und Monat vertauscht. Jeder sieht in einem schnellen Test richtig aus und scheitert an den
Randfällen.
ExcelMaster schreibt die
kalenderkorrekte Fassung. Beschreiben Sie die Berechnung — „erster Werktag des nächsten Monats", „Rechnung
fällig in 45 Tagen", „Monate zwischen zwei Datumswerten" — und es wählt schlichte Arithmetik für Tage,
DateAdd mit dem richtigen Intervallcode für Monate und Jahre und DateSerial, um ohne regionale
Mehrdeutigkeit aus Teilen zu bauen, und rechnet DateDiff-Grenzzählungen in echte Zeiträume um. Sie
beschreiben das Datum, das Sie brauchen; es schreibt die Rechnung, die Monatsenden und Schaltjahre
übersteht.
Häufig gestellte Fragen
Wie addiere ich in VBA Tage zu einem Datum?
Nehmen Sie einfach Arithmetik: Ein Datum ist eine Anzahl Tage, also addiert newDate = myDate + 7 eine
Woche, und myDate - 1 ist gestern. VBA rollt Monatsenden und Schaltjahre für Sie, wenn Sie ganze
Tage addieren. Greifen Sie nur dann zu DateAdd, wenn die Einheit ein Monat oder ein Jahr ist, denn
die haben keine feste Anzahl Tage.
Was ist der Unterschied zwischen DateAdd und dem bloßen + in VBA?
Schlichtes + addiert Tage und ist für Tagesrechnung korrekt. DateAdd(interval, number, date)
versteht den Kalender, also addiert DateAdd("m", 1, …) einen echten Monat — aus 31. Jan wird
28. Feb, kein unmöglicher 31. — und DateAdd("yyyy", 1, …) meistert Schaltjahre. Nehmen Sie + für
Tage; nehmen Sie DateAdd für Monate und Jahre, wo + 30 oder + 365 driften würde.
Warum liefert DateDiff in VBA die falsche Anzahl Jahre?
Weil DateDiff("yyyy", …) überschrittene Jahresgrenzen zählt, nicht verstrichene Jahre. Vom 31.
Dezember zum 1. Januar liefert es 1, obwohl nur ein Tag verging. Für ein Alter oder echte verstrichene
Jahre berechnen Sie DateDiff("yyyy", dob, Date) und ziehen 1 ab, wenn der diesjährige Geburtstag noch
nicht war. Nehmen Sie "d", wenn Sie eine wörtliche Zählung der Tage wollen.
Was bedeuten die Intervallcodes in DateAdd?
Es sind String-Codes für die Einheit: "yyyy" Jahr, "q" Quartal, "m" Monat, "ww" Woche, "d" Tag,
"h" Stunde, "n" Minute, "s" Sekunde. Die zwei Fallen sind, dass Minute "n" ist, nicht "m"
(das ist Monat) und dass "y" den Tag des Jahres meint, nicht das Jahr (Jahr ist "yyyy").
Dieselben Codes gelten in DateDiff und DatePart.
Wie bekomme ich in VBA den letzten Tag des Monats?
Nehmen Sie DateSerial mit Tag 0 des nächsten Monats: DateSerial(Year(d), Month(d) + 1, 0). Tag 0 ist
als der letzte Tag des Vormonats definiert, also liefert das den letzten Tag von ds Monat, ohne
Monatslängen-Tabelle und ohne Schaltjahr-Sonderfall. DateSerial baut Datumswerte auch aus Teilen, ohne
die regionale Tag/Monat-Mehrdeutigkeit des Zeichenketten-Parsens.
Getestet in
Getestet in: Excel 365 (Windows 11), VBA 7.1 — zuletzt geprüft am 26.08.2026.
Verwandte Anleitungen: VBA Now, Date & Time · VBA Weekday & DatePart · VBA CStr, CDate & Val · VBA Format · VBA For Loop
