Wenn Sie jemals einen Beitrag live geschaltet haben, nur um auf der öffentlichen Seite die Kennzeichnung „vor 57 Jahren“ zu sehen, während Ihr Dashboard ruhig behauptet, er sei zehn Minuten nach der vollen Stunde veröffentlicht worden, dann kennen Sie den besonderen Schmerz dieses Bugs. Er zerstört nicht das Layout. Er löst keinen fatalen Fehler aus. Er lässt Ihren Inhalt einfach ein halbes Jahrhundert altern, und das bloße Starren auf Ihre Theme-Dateien wird die Zahl nicht ändern.

Dieses Problem übersteht meist die üblichen Kontrollen. Sie durchsuchen mit grep die Dateien single.php, archive.php und functions.php auf der Suche nach einem fehlerhaften get_the_date()-Aufruf. Alles sieht standardmäßig aus. Sie laden die Live-Seite neu. Der Geist von 1968 spukt immer noch in Ihrer Autorenzeile herum. An diesem Punkt hat das Problem fast nichts mit Ihren Templates zu tun, sondern alles damit, wie die Zeit durch den WordPress-Stack fließt.

Warum genau diese Zahl immer wieder erscheint

Die Angabe „vor 57 Jahren“ ist nicht zufällig. WordPress-Themes zeigen relative Zeitangaben oft über die Funktion human_time_diff() an, die den Zeitstempel eines Beitrags mit dem aktuellen Moment vergleicht und eine freundliche Phrase wie „vor 2 Stunden“ ausgibt. Damit diese Berechnung funktioniert, benötigt PHP einen gültigen Unix-Zeitstempel – eine Zählung der Sekunden seit dem 1. Januar 1970, dem Unix-Epoch.

Wenn etwas den Zeitstempel entfernt oder beschädigt, bevor er diese Berechnung erreicht, vergleicht die Funktion häufig Null (oder einen ähnlich ungültigen Ausgangspunkt) mit der aktuellen Zeit. Das Ergebnis ist ein Zeitraum, der etwa fünfeinhalb Jahrzehnte zurückreicht und Jahr für Jahr voranschreitet. Es ist ein Symptom eines fehlenden oder falsch gelesenen Zeitwerts, nicht einer Datenbank voller Retro-Blogposts.

Die Täuschung im Dashboard

Einer der frustrierendsten Aspekte dieses Bugs ist die gespaltene Persönlichkeit Ihres Admin-Panels. Innerhalb von wp-admin zeigt die Beitragsliste das korrekte Veröffentlichungsdatum an, da WordPress dieses oft direkt aus der MySQL-Tabelle wp_posts abruft und serverseitig formatiert, ohne es durch den Filter für relative Zeitangaben laufen zu lassen. Das Frontend hingegen verlässt sich möglicherweise auf ein Theme oder Plugin, das human_time_diff() aufruft, oder es leitet den rohen Datenbankwert durch eine Kette von PHP-Zeitzonenkonvertierungen weiter, die das Backend komplett umgeht.

Die Daten sind also meistens noch intakt. Es ist die Pipeline zwischen der Datenbank und dem gerenderten HTML, die einen Knick bekommt.

PHP-Version und Zeitzoneneinstellungen

Beginnen wir mit PHP. Hosting-Panels lassen Versionswechsel harmlos erscheinen, aber PHP behandelt Zeitobjekte über die verschiedenen Hauptversionen hinweg unterschiedlich. Eine Website, die veralteten PHP 7.4-Code in einer plötzlich umgestellten PHP 8.1-Umgebung ausführt, kann subtile Verschiebungen bei der Initialisierung von DateTime-Objekten mit leeren oder fehlerhaften Strings erleben. Wenn Ihre php.ini-Datei date.timezone undefiniert lässt, verwendet PHP standardmäßig UTC und geht davon aus, dass der Server es am besten weiß. WordPress sieht das möglicherweise anders.

Prüfen Sie, ob jemand eine Zeitzonendeklaration fest in die wp-config.php geschrieben hat. Eine Zeile wie date_default_timezone_set( 'Asia/Kolkata' ); mag hilfreich erscheinen, aber WordPress erwartet, seine eigene Uhr über den Wert unter Settings > General zu verwalten. Das Erzwingen eines Offsets auf PHP-Ebene kann eine Race Condition verursachen, bei der der WordPress-Core glaubt, die Zeit sei lokal, während PHP glaubt, sie sei universell. Wenn diese Offsets während einer Zeitstempelkonvertierung kollidieren, kann das an Ihr Template zurückgegebene Ergebnis auf Null zurückfallen.

Server-Zeitzonen-Konfigurationen

Ihr MySQL-Server hat seine eigene Vorstellung von der Lokalzeit. WordPress schreibt für jeden Beitrag zwei Daten: post_date in der Lokalzeit der Website und post_date_gmt in der Weltzeit (UTC). Wenn sich die globale time_zone der Datenbank ändert – zum Beispiel nach einer Migration von SYSTEM zu +00:00 – kann es sein, dass strtotime() von PHP den gespeicherten String nicht mit dem in Einklang bringen kann, was es erwartet. Die Datenbank speichert zwar weiterhin 2024-03-15 14:30:00, aber der Kontext verschiebt sich, und die geparste Ausgabe wird in PHP zu false oder null.

Praxisbeispiel: Ein Managed Host verschiebt Ihre Datenbank von einem Knoten, der MySQL 5.7 mit SYSTEM-Zeit nutzt, auf einen Cluster mit MariaDB 10.11, der auf striktes UTC eingestellt ist. Ihr Theme ändert sich nicht. Ihre WordPress-Einstellungen ändern sich nicht. Dennoch gibt get_the_time( 'U' ) – das Unix-Zeitstempelformat – plötzlich für einige Beiträge einen leeren Wert zurück, und die Funktion für relative Zeitangaben fällt auf diese Epoch-Null-Berechnung zurück. Die Lösung besteht darin, die Zeitzone der Anwendung, die Zeitzone der Datenbank und die Systemuhr des Betriebssystems aufeinander abzustimmen, damit WordPress nicht raten muss, welchen Bezugsrahmen es verwenden soll.

Datenbank-Zeitstempelformate

Der WordPress-Kern speichert Beitragsdaten in MySQL DATETIME-Spalten, nicht in TIMESTAMP-Feldern. Diese Unterscheidung ist wichtig, da DATETIME in älteren MySQL-Versionen einen Kalenderwert ohne Berücksichtigung der Zeitzone speichert, während TIMESTAMP im Hintergrund alles in UTC umwandelt. Wenn ein Plugin oder ein Migrations-Tool Ihr wp_posts-Schema geändert hat oder wenn ein altes Backup ungültige Null-Daten in die Tabelle wiederhergestellt hat, liest WordPress möglicherweise einen Wert wie 0000-00-00 00:00:00 und gibt diesen stillschweigend an Ihr Theme weiter.

Moderne MySQL-Modi, insbesondere NO_ZERO_DATE und STRICT_TRANS_TABLES, lehnen diese Null-Platzhalter ab. Wenn ein Backup-Skript diese während einer Migration eingefügt hat, hat die Datenbank sie beim Import möglicherweise gekürzt oder auf NULL gesetzt. Sie können dies schnell mit einer direkten SQL-Abfrage überprüfen:

SELECT ID, post_title, post_date, post_date_gmt 
FROM wp_posts 
WHERE post_status = 'publish' 
ORDER BY post_date DESC 
LIMIT 10;

Wenn die Rohdaten in den Spalten korrekt aussehen, die Website aber immer noch veraltete Daten anzeigt, tritt die Korruption nach der Abfrage auf. Wenn die Spalten selbst Nullen enthalten, haben Sie das Leck in der Leitung gefunden.

Plugin-Konflikte mit Datumsfunktionen

Plugins, die die Datumsausgabe filtern, sind häufige Schuldige. Mehrsprachige Tools wie WPML oder Polylang haken sich in get_the_date ein, um Monatsnamen zu übersetzen. Caching-Plugins fangen das fertige HTML ab. Jede dieser Ebenen kann versehentlich einen unformatierten String an eine Funktion übergeben, die einen Unix-Integer erwartet.

Ein Übersetzungs-Plugin ersetzt möglicherweise „March 15, 2024“ durch die lokalisierte Entsprechung, aber wenn ein Theme diesen lokalisierten String dann innerhalb einer benutzerdefinierten Funktion an strtotime() weiterleitet, schlägt der Parser bei Nicht-Englisch-Zeichen fehl und gibt false zurück. Dieser false-Wert gelangt an human_time_diff(), was den Wert Null mit der aktuellen Zeit vergleicht und so die berüchtigte Lücke von einem halben Jahrhundert erzeugt.

Object-Cache-Ebenen erschweren dies zusätzlich. Redis oder Memcached können ein serialisiertes WP_Post-Objekt aus einer Anfrage speichern, bei der das Parsen des Datums kurzzeitig fehlgeschlagen ist. Jeder nachfolgende Besucher erhält dieses korrupte Objekt direkt aus dem RAM, wodurch die Datenbank komplett umgangen wird. Das Problem besteht auf der Live-Seite fort, weil Ihr Produktions-Stack über eine Cache-Infrastruktur verfügt, die Ihrer lokalen Installation fehlt.

Eine praktische Checkliste zur Fehlersuche

Da das Symptom tief im Stack verborgen ist, müssen Sie die Ebenen systematisch abtragen, bis die Daten wieder korrekt angezeigt werden.

  1. Fragen Sie die Datenbank direkt ab. Öffnen Sie phpMyAdmin oder nutzen Sie WP-CLI und prüfen Sie die Rohwerte von post_date. Wenn diese korrekt sind, ist die Datenbank nicht das Problem.
  2. Wechseln Sie zu einem Standard-Theme. Aktivieren Sie Twenty Twenty-Four oder Twenty Twenty-Three. Wenn der Fehler verschwindet, prüfen Sie Ihr aktives Theme und Child-Theme auf benutzerdefinierte Funktionen, die die Zeitausgabe umschließen.
  3. Deaktivieren Sie die Plugins. Benennen Sie den Ordner /wp-content/plugins vorübergehend um oder deaktivieren Sie alle Plugins über das Dashboard. Aktivieren Sie sie einzeln wieder und prüfen Sie nach jeder Aktivierung das Frontend.
  4. Lesen Sie das Error-Log. Suchen Sie nach Zeitzonen-Warnungen, DateTime-Fehlern oder strtotime()-Beschwerden. Sie weisen oft genau auf den