In vielen Anwendungen spielen Zeitspannen eine zentrale Rolle. Ob ein Abonnement in 30 Tagen abläuft, eine Erinnerung vier Stunden vor einem Termin verschickt werden soll oder die Differenz zwischen zwei Datumsangaben angezeigt wird: All diese Aufgaben erfordern den Umgang mit Zeitintervallen. PHP stellt dafür die Klasse DateInterval bereit. Sie repräsentiert eine definierte Zeitspanne aus Jahren, Monaten, Tagen, Stunden, Minuten und Sekunden. In diesem Tutorial lernst du, wie du ein DateInterval erzeugst, es formatierst und mit DateTime kombinierst, um Datums- und Zeitberechnungen durchzuführen.

Der erste Schritt ist das Verständnis der Klasse selbst, ihrer Eigenschaften und der verschiedenen Erzeugungswege.
Was ist ein DateInterval?
Die Klasse DateInterval ist seit PHP 5.3 verfügbar und gehört zu den eingebauten Datums- und Zeitklassen. Ein Objekt dieser Klasse beschreibt eine relative Zeitspanne, also beispielsweise „1 Jahr, 2 Monate und 10 Tage“. Diese Zeitspanne ist nicht an ein konkretes Datum gebunden. Erst wenn sie mit einem DateTime-Objekt kombiniert wird, ergibt sich ein neues konkretes Datum. Ein DateInterval besitzt öffentliche Eigenschaften für jede Einheit: $y für Jahre, $m für Monate, $d für Tage, $h für Stunden, $i für Minuten und $s für Sekunden. Zusätzlich gibt es die Eigenschaft $invert, die angibt, ob das Intervall negativ ist, und die Eigenschaft $days, die bei aus diff() erzeugten Intervallen die Gesamtzahl der Tage enthält.
Die Klasse DateInterval wird in PHP vor allem in drei Szenarien eingesetzt. Erstens als Eingabe für die Methoden DateTime::add() und DateTime::sub(), um ein Datum um eine bestimmte Zeitspanne zu verschieben. Zweitens als Rückgabewert der Methode DateTime::diff(), die den Abstand zwischen zwei Zeitpunkten berechnet. Drittens als Taktgeber für die Klasse DatePeriod, mit der sich wiederholende Intervalle erzeugen lassen.
Das folgende Diagramm zeigt die verschiedenen Möglichkeiten, ein DateInterval zu erzeugen und einzusetzen.
graph TD
A[Konstruktor P1Y2M3D] --> B[DateInterval]
C[createFromDateString] --> B
D[DateTime::diff] --> B
B --> E[add / sub]
B --> F[format]
B --> G[DatePeriod]
Ein DateInterval erzeugen
PHP bietet zwei Wege, ein DateInterval-Objekt zu erstellen. Der Konstruktor erwartet einen String im ISO-8601-Duration-Format, während die statische Methode createFromDateString() eine natürlichsprachliche Beschreibung akzeptiert. Zusätzlich liefert die Methode DateTime::diff() ein DateInterval als Ergebnis zurück, das die Differenz zwischen zwei Zeitpunkten beschreibt.
ISO-8601-Duration-Format (P1Y2M3D)
Der Konstruktor der Klasse DateInterval erwartet einen String, der dem ISO-8601-Standard für Zeitspannen folgt. Dieser String beginnt immer mit dem Buchstaben P (für Period). Danach folgen die Einheiten: Y für Jahre, M für Monate und D für Tage. Wenn Zeitangaben (Stunden, Minuten, Sekunden) enthalten sind, wird der Buchstabe T als Trennzeichen eingefügt. Nach dem T stehen H für Stunden, M für Minuten und S für Sekunden. Das Zeichen M hat also je nach Position eine unterschiedliche Bedeutung: Vor dem T steht es für Monate, nach dem T für Minuten.
<?php
/* 1 Jahr, 2 Monate, 10 Tage */
$intervall = new DateInterval('P1Y2M10D');
/* 4 Stunden, 30 Minuten */
$zeit = new DateInterval('PT4H30M');
Ein Intervall wie P1Y2M10DT4H30M beschreibt 1 Jahr, 2 Monate, 10 Tage, 4 Stunden und 30 Minuten. Nicht benötigte Bestandteile können weggelassen werden: P10D reicht für 10 Tage, PT1H für eine Stunde. Der Buchstabe P am Anfang ist jedoch immer Pflicht. Fehlt er, wirft PHP eine Exception. Ebenso ist es nicht möglich, negative Werte im ISO-8601-String anzugeben. Ein String wie P-2D ist ungültig und führt zu einem Fehler. Für negative Intervalle wird stattdessen die invert-Eigenschaft verwendet, die später in diesem Tutorial behandelt wird.
createFromDateString als Alternative
Die statische Methode DateInterval::createFromDateString() akzeptiert einen englischsprachigen String, der die Zeitspanne in natürlicher Sprache beschreibt. Diese Methode ist oft lesbarer als das ISO-8601-Format, besonders bei einfachen Zeitspannen.
<?php
$intervall = DateInterval::createFromDateString('3 months 10 days');
$woche = DateInterval::createFromDateString('1 week');
Die Methode versteht Begriffe wie year, month, day, week, hour, minute und second sowie deren Pluralformen. Auch Kombinationen wie 3 months 10 days sind möglich. Der Vorteil gegenüber dem Konstruktor liegt in der besseren Lesbarkeit. Der Nachteil ist, dass ausschließlich englische Begriffe verstanden werden. Im Unterschied zum Konstruktor gibt diese Methode bei einem ungültigen String false zurück, statt eine Exception zu werfen. Das macht sie besonders geeignet, wenn Intervalle aus Benutzereingaben oder Konfigurationsdateien stammen und eine sanfte Fehlerbehandlung gewünscht ist.
DateInterval formatieren
Sobald ein DateInterval-Objekt existiert, kann es in eine lesbare Zeichenkette umgewandelt werden. PHP stellt dafür die Methode format() bereit, die ähnlich wie sprintf() mit Platzhaltern arbeitet.
Die format-Methode und ihre Platzhalter
Die Methode format() verwendet Platzhalter, die mit dem Zeichen % beginnen. Die wichtigsten Platzhalter sind:
%y und %Y für Jahre (ohne bzw. mit führender Null) %m und %M für Monate %d und %D für Tage %h und %H für Stunden %i und %I für Minuten %s und %S für Sekunden %a für die Gesamtzahl der Tage (nur bei Intervallen aus diff()) %r für das Vorzeichen (Minuszeichen bei negativen Intervallen, sonst leer)
<?php
$start = new DateTime('2025-01-01');
$ende = new DateTime('2025-06-15');
$diff = $start->diff($ende);
echo $diff->format('%m Monate und %d Tage');
/* 5 Monate und 14 Tage */
Ein häufiger Stolperstein ist das Verhalten von %m und %d. Diese Platzhalter geben nicht die Gesamtzahl der Monate oder Tage aus, sondern nur den verbleibenden Anteil nach Abzug der größeren Einheiten. Bei einer Differenz von 1 Jahr und 3 Monaten liefert %m den Wert 3, nicht 15. Die Gesamtzahl der Tage steht in %a zur Verfügung, allerdings nur bei Intervallen, die durch DateTime::diff() erzeugt wurden. Bei manuell erstellten Intervallen gibt %a den Wert (unknown) zurück, da PHP die tatsächliche Anzahl der Tage nicht berechnen kann, ohne einen konkreten Startpunkt zu kennen.
Die Methode DateInterval::format() arbeitet anders als DateTime::format(). Während DateTime::format() einen Formatstring mit Buchstaben wie d, m und Y erwartet, verwendet DateInterval::format() Platzhalter mit vorangestelltem Prozentzeichen. Eine Verwechslung dieser beiden Methoden ist eine verbreitete Fehlerquelle.
DateInterval mit DateTime kombinieren
Die eigentliche Stärke von DateInterval zeigt sich in der Kombination mit DateTime. Durch die Methoden add() und sub() lässt sich ein Datum gezielt in die Zukunft oder Vergangenheit verschieben.
Tage addieren mit add()
Die Methode DateTime::add() nimmt ein DateInterval entgegen und verschiebt das Datum um die angegebene Zeitspanne nach vorn. Das ursprüngliche DateTime-Objekt wird dabei direkt verändert.
<?php
$datum = new DateTime('2025-01-15');
$intervall = new DateInterval('P30D');
$datum->add($intervall);
echo $datum->format('d.m.Y'); /* 14.02.2025 */
Soll das ursprüngliche Datum erhalten bleiben, empfiehlt sich die Verwendung von DateTimeImmutable. Bei dieser Variante gibt add() ein neues Objekt zurück, ohne das Original zu verändern. Gerade in Schleifen oder bei mehrfacher Verwendung desselben Ausgangsdatums ist DateTimeImmutable die sicherere Wahl, weil keine unbeabsichtigten Seiteneffekte auftreten. Da die Methode das Objekt auch zurückgibt, lassen sich Aufrufe verketten, beispielsweise $datum->add($intervall1)->add($intervall2).
Zeitspannen subtrahieren mit sub()
Die Methode DateTime::sub() funktioniert analog zu add(), verschiebt das Datum aber in die Vergangenheit. Sie erwartet ebenfalls ein DateInterval-Objekt als Parameter.
<?php
$datum = new DateTime('2025-06-15');
$intervall = new DateInterval('P3M');
$datum->sub($intervall);
echo $datum->format('d.m.Y'); /* 15.03.2025 */
Alternativ zur Methode sub() kann auch add() mit einem invertierten Intervall verwendet werden. Beide Ansätze führen zum gleichen Ergebnis. Welche Variante gewählt wird, ist eine Frage der Lesbarkeit und des persönlichen Stils.
Negative Intervalle und die invert-Eigenschaft
Das ISO-8601-Duration-Format unterstützt keine negativen Zeitspannen. Um ein negatives Intervall zu erzeugen, wird die öffentliche Eigenschaft $invert auf den Wert 1 gesetzt. Ein invertiertes Intervall kehrt die Wirkung von add() um: Statt in die Zukunft verschiebt es das Datum in die Vergangenheit.
<?php
$intervall = new DateInterval('P2D');
$intervall->invert = 1;
$datum = new DateTime('2025-06-15');
$datum->add($intervall);
echo $datum->format('d.m.Y'); /* 13.06.2025 */
Auch die Methode DateTime::diff() setzt die invert-Eigenschaft automatisch, wenn das Enddatum vor dem Startdatum liegt. Das Ergebnis zeigt dann, dass die Zeitspanne rückwärts gerichtet ist. Diese Eigenschaft lässt sich in der format()-Methode mit dem Platzhalter %r auslesen. Er gibt ein Minuszeichen aus, wenn invert den Wert 1 hat, und bleibt andernfalls leer.
<?php
$frueh = new DateTime('2025-06-01');
$spaet = new DateTime('2025-03-01');
$diff = $frueh->diff($spaet);
echo $diff->format('%r%m Monate'); /* -3 Monate */
echo $diff->invert; /* 1 */
In der Praxis wird die invert-Eigenschaft selten manuell gesetzt, da sub() in den meisten Fällen die elegantere Lösung ist. Sie ist jedoch unverzichtbar, wenn ein Intervall abhängig von einer Bedingung sowohl positiv als auch negativ sein soll.
DatePeriod: Wiederholende Intervalle
Die Klasse DatePeriod ermöglicht es, ein Intervall wiederholt auf ein Startdatum anzuwenden und so eine Reihe von Zeitpunkten zu erzeugen. Sie wird häufig eingesetzt, um regelmäßige Termine, Abrechnungszeiträume oder Kalenderwochen zu generieren.
<?php
$start = new DateTime('2025-01-01');
$intervall = new DateInterval('P1M');
$ende = new DateTime('2025-06-01');
$zeitraum = new DatePeriod($start, $intervall, $ende);
foreach ($zeitraum as $datum) {
echo $datum->format('d.m.Y') . "\n";
}
/* 01.01.2025 */
/* 01.02.2025 */
/* 01.03.2025 */
/* 01.04.2025 */
/* 01.05.2025 */
Der Konstruktor von DatePeriod erwartet ein Startdatum, ein Intervall und entweder ein Enddatum oder die Anzahl der Wiederholungen als Integer. Das Startdatum ist standardmäßig im Ergebnis enthalten, das Enddatum hingegen nicht. Mit der Konstante DatePeriod::EXCLUDE_START_DATE als viertem Parameter kann das Startdatum ausgeschlossen werden. Die Klasse implementiert das Interface Traversable, sodass sie direkt in einer foreach-Schleife verwendet werden kann. Jedes Element der Iteration ist ein DateTime-Objekt (oder DateTimeImmutable, wenn das Startdatum diesen Typ hat).
Typische Anwendungsfälle für DatePeriod sind die Erzeugung aller Montage in einem bestimmten Zeitraum, die Berechnung monatlicher Fälligkeitstermine oder die Erstellung täglicher Zeitreihen für Diagramme. In Kombination mit DateInterval und DateTime bildet DatePeriod ein leistungsfähiges Werkzeug für alle Arten von kalendarischen Berechnungen.
Fazit
Die Klasse DateInterval ist ein unverzichtbares Werkzeug für die Arbeit mit Zeitspannen in PHP. Sie bietet zwei Wege zur Erzeugung: den Konstruktor mit ISO-8601-Duration-Format und die statische Methode createFromDateString(). Mit DateTime::diff() lassen sich Intervalle direkt aus der Differenz zweier Zeitpunkte berechnen. Die Methoden add() und sub() verschieben Datumsangaben in die Zukunft oder Vergangenheit, während format() die Zeitspanne in eine lesbare Zeichenkette umwandelt. Negative Intervalle werden über die invert-Eigenschaft abgebildet. Die Klasse DatePeriod ergänzt dieses System um die Möglichkeit, wiederholende Zeiträume zu erzeugen. Dabei lohnt es sich, die Stolperfallen im Blick zu behalten: Der Platzhalter %a funktioniert nur bei Intervallen aus diff(), negative Werte im Konstruktor sind nicht möglich und %m zeigt stets nur die restlichen Monate an. Wer diese Klassen sicher beherrscht, kann nahezu jede zeitbezogene Anforderung in PHP sauber und wartbar umsetzen.