vlibDate: Datumsberechnungen in PHP
Wofür die Klasse gedacht war, welche Aufgaben heute DateTime und DateInterval übernehmen und wie eine Ablösung ohne Verhaltensänderung aussieht.
Das Wichtigste
- vlibDate entstand, als PHP für Datumsrechnung nur Unix-Zeitstempel und
mktimeanbot – mit Grenzen bei Zeiträumen ausserhalb der 32-Bit-Spanne. - Seit PHP 5.2 deckt
DateTimeImmutablemitDateIntervalundDateTimeZonedenselben Bedarf ab, korrekt über Zeitzonen und Sommerzeit hinweg. - Bei einer Ablösung ist die Zeitzone die häufigste Fehlerquelle: alte Berechnungen liefen oft implizit in der Serverzeitzone.
-
DateTimeImmutablestattDateTimeverwenden – die veränderliche Variante ändert das Objekt in place und erzeugt schwer auffindbare Fehler.
vlibDate stammt aus einer Zeit, in der PHP für Datumsrechnung wenig mehr anbot als Unix-Zeitstempel. Wer heute alten Code übernimmt, findet die Klasse in Bestandsprojekten – und braucht meist nur zu wissen, was sie tat und wodurch man es ersetzt.
Das Problem, das sie löste
Vor PHP 5.2 war Datumsrechnung mühsam:
- Zeitstempel sind auf 32-Bit-Systemen auf den Bereich von 1901 bis 2038 begrenzt.
- Rechnen mit Sekunden ignoriert die Sommerzeitumstellung: Ein Tag hat zweimal im Jahr nicht 86.400 Sekunden.
- Monatsarithmetik ist unangenehm, weil Monate unterschiedlich lang sind.
- Kalenderwochen nach ISO 8601 muss man von Hand bestimmen.
vlibDate kapselte diese Punkte in einer Klasse mit Methoden zum Addieren von Zeiträumen, zum Bilden von Differenzen und zum Formatieren.
Was PHP heute mitbringt
<?php
$start = new DateTimeImmutable('2026-03-28 12:00:00', new DateTimeZone('Europe/Berlin'));
// Zeiträume addieren
$morgen = $start->add(new DateInterval('P1D'));
$inDreiWochen = $start->add(new DateInterval('P3W'));
$naechstesJahr = $start->add(new DateInterval('P1Y'));
// Differenz
$diff = $start->diff(new DateTimeImmutable('2026-12-24', new DateTimeZone('Europe/Berlin')));
echo $diff->days; // Anzahl voller Tage
echo $diff->m; // volle Monate innerhalb des Rests
// ISO-Kalenderwoche
echo $start->format('o-\WW'); // 2026-W13
Der DateInterval-Aufbau ist gewöhnungsbedürftig: P leitet den Zeitraum ein, T trennt Datums- von Zeitanteil. P1DT2H sind ein Tag und zwei Stunden, PT1M ist eine Minute, P1M ein Monat. Die Verwechslung von P1M und PT1M ist ein klassischer Fehler.
Der Punkt, an dem alte Rechnungen falsch werden
// FALSCH über die Sommerzeitumstellung hinweg
$tage = (int) (($ende - $start) / 86400);
// RICHTIG
$tage = $start->diff($ende)->days;
Am letzten Sonntag im März hat der Tag 23 Stunden, am letzten im Oktober 25. Wer mit Zeitstempeln und einer festen Sekundenzahl rechnet, bekommt an diesen Tagen ein um eins verschobenes Ergebnis. In einer Fristberechnung ist das ein echter Fehler.
Dasselbe gilt für Monate:
$ende = (new DateTimeImmutable('2026-01-31'))->add(new DateInterval('P1M'));
echo $ende->format('Y-m-d'); // 2026-03-03
PHP addiert einen Monat auf den 31. Januar, landet beim 31. Februar und normalisiert auf den 3. März. Wenn “ein Monat später” den letzten Tag des Folgemonats meinen soll, muss das explizit gerechnet werden:
$ende = (new DateTimeImmutable('2026-01-31'))->modify('last day of next month');
echo $ende->format('Y-m-d'); // 2026-02-28
Ablösung planen
- Alle Aufrufstellen finden.
grep -rn 'vlibDate' src/liefert die Liste. - Zeitzone festnageln. Alte Berechnungen liefen häufig implizit in der Serverzeitzone. Setze
date.default_timezoneexplizit und prüfe, ob die neuen Ergebnisse denen der alten Klasse entsprechen. - Erwartete Werte festhalten, bevor du etwas änderst. Für jede Aufrufstelle ein paar Eingaben mit dem Ergebnis der alten Klasse notieren – am besten als Testfall. Ohne diesen Vergleich merkt niemand, wenn sich das Verhalten an einem Randfall verschiebt.
- Randfälle gezielt prüfen: Schaltjahre, Monatsenden, die beiden Umstellungstage, Datumsangaben vor 1970 und nach 2038.
DateTimeImmutableverwenden, nichtDateTime.
Der letzte Punkt lohnt die Erklärung:
$start = new DateTime('2026-01-01');
$ende = $start;
$ende->add(new DateInterval('P1M'));
echo $start->format('Y-m-d'); // 2026-02-01 - $start hat sich mitverändert
Mit DateTimeImmutable passiert das nicht, weil jede Operation ein neues Objekt zurückgibt. In gewachsenem Code, in dem Datumsobjekte durch mehrere Funktionen gereicht werden, ist das der Unterschied zwischen einem nachvollziehbaren Programm und einer stundenlangen Fehlersuche.
Ausgabe in deutscher Schreibweise
$formatter = new IntlDateFormatter(
'de_DE',
IntlDateFormatter::LONG,
IntlDateFormatter::NONE,
'Europe/Berlin'
);
echo $formatter->format($start); // 28. März 2026
IntlDateFormatter setzt die intl-Erweiterung voraus, liefert dafür aber korrekte Monatsnamen und Formate für jede Sprache. Ohne intl bleibt format('d.m.Y') – das reicht für numerische Ausgaben, nicht für ausgeschriebene Monate.
Häufige Fragen
Kann ich vlibDate einfach weiterbenutzen?
Solange der Code auf der eingesetzten PHP-Version läuft, spricht fachlich wenig dagegen. Neue Berechnungen sollten aber mit DateTimeImmutable geschrieben werden – dann wächst der alte Anteil nicht weiter.
Was ist der Unterschied zwischen DateTime und DateTimeImmutable?
DateTime ändert sich bei modify oder add selbst. Wer das Objekt an eine Funktion übergibt, kann es dort unbemerkt verändern. DateTimeImmutable gibt bei jeder Operation ein neues Objekt zurück und lässt das ursprüngliche unangetastet.
Warum stimmt meine Differenz um eine Stunde nicht?
Fast immer Sommerzeit. Wer mit Zeitstempeln rechnet und durch 86400 teilt, bekommt an den Umstellungstagen ein falsches Ergebnis. DateTimeImmutable mit korrekt gesetzter Zeitzone rechnet richtig, weil es die Umstellung kennt.
Welche Zeitzone sollte ich setzen?
Speichern in UTC, rechnen in UTC, nur zur Anzeige in die lokale Zone umrechnen. Setze date.default_timezone explizit in der Konfiguration, statt dich auf den Serverstandard zu verlassen – der unterscheidet sich zwischen Entwicklungs- und Produktivsystem regelmässig.
Weiterlesen
- vlibTemplate: Aufbau, Syntax und Beispiele
Platzhalter, Schleifen, Bedingungen und Includes der klassischen Engine - inklusive Hinweisen zum Betrieb auf aktuellen PHP-Versionen.
- vlibMimeMail: HTML-Mails mit Anhängen
MIME-Aufbau, Text- und HTML-Teil, Anhänge und Kodierung - und was du heute stattdessen einsetzen solltest.
- Template-Engines in PHP: Übersicht
Was eine Engine gegenüber purem PHP bringt, welche Ansätze es gibt und wie du für ein Projekt entscheidest.
- Smarty: Grundlagen und typische Muster
Zuweisungen, Modifier, Blöcke und Caching - und wo Smarty in modernen Projekten noch seinen Platz hat.