Zeitzone sind eine Lüge (und wie man sie in Code behandelt)
Zeitzone sind zunächst wie einfache UTC-Abweichungen. Doch das ist nicht der Fall. Dieser Leitfaden erklärt, warum Zeitzone Code stören – durch Sommerzeitlücken, halbe Stundeneinstellungen und naive Datumsangaben – und zeigt, wie sie korrekt in JavaScript, Python, PHP und SQL behandelt werden können.
Sie haben Ihrem Server gefragt, um welche Uhrzeit es ist. Es sagte 14:00. Sie haben es gespeichert. Sie haben es erneut abgefragt. Jetzt sagt es 16:00. Sie haben nichts geändert. Willkommen bei Zeitzone-Problemata.
Zeitzone sind eines der komplexesten Probleme im Softwarebereich. Auf der Oberfläche sehen sie aus wie eine einfache UTC-Abweichung – einfach einige Stunden addieren oder subtrahieren. Im Inneren sind sie jedoch ein chaotischer Mix aus politischen Entscheidungen, historischen Zufällen, halbstündigen Abweichungen und Tagesschichtregeln, die mit wenig Ankündigung geändert werden. Dieser Artikel erklärt, warum Zeitzone so problematisch sind und, wichtigerweise, wie man sie tatsächlich korrekt in Code behandelt.
Warum „Nur UTC verwenden“ nur die Hälfte der Lösung ist
Der häufigste Rat, den Sie hören, lautet: Alles in UTC speichern. Dieser Rat ist korrekt – aber unvollständig. Das Speichern in UTC löst das Problem (konsistente Speicherung) auf, lässt jedoch ein größeres Problem unbehandelt: die Anzeige und Eingabe. einen Ein Benutzer in Tokio plant einen Termin um 9 Uhr seiner Zeit. Sie speichern das als UTC. Später öffnet ein Benutzer in New York den gleichen Termin. Sie zeigen ihn in seiner lokalen Zeit an. Aber welche lokale Zeit gilt, wenn der Benutzer reist? Wenn er sein Systemzeitgerät aktualisiert? Wenn die Tagesschicht beginnt? „Speichern Sie UTC, zeigen Sie lokale Zeit an“ ist eine solide Politik – es ist die
Ausführung die die meisten Teams zerstört. Die tatsächlichen Probleme mit Zeitzone
Bevor wir zu Lösungen kommen, hilft es, genau zu nennen, was man tatsächlich bekämpft.
1. UTC-Abweichungen sind keine Zeitzone
ist nicht „Indienzeit“. Es ist eine statische Abweichung. Indien Standardzeit ist
UTC+5:30 — eine benannte Zeitzone, die zwar +5:30 verwendet und niemals Tagesschicht beobachtet. Es handelt sich um zwei verschiedene Dinge. Wenn Sie eine Abweichung festlegen, speichern Sie eine Zahl. Wenn Sie eine benannte Zone speichern, speichern Sie die Absicht. Asia/Kolkata Benannte Zeiten leben in der
IANA Zeitzone-Datenbank (auch als tzdata oder Olson-Datenbank bekannt). Jede ernsthafte Programmiersprache und Betriebssystem enthält eine Kopie davon. Verwenden Sie sie. Verwenden Sie immer statt America/New_York 2. Tagesschicht verschiebt die Uhr (unvorhersehbar) UTC-5.
DST-Übergänge erzeugen zwei wirklich gefährliche Randfälle:
Der „Frühlingssprung“-Lücke:
- Die Uhren springen von 2:00 Uhr auf 3:00 Uhr. Die Zeit 2:30 Uhr existiert tatsächlich nicht. Wenn Sie etwas auf 2:30 Uhr an jenem Tag planen, erhalten Sie entweder einen Fehler oder eine leise Fehlverhalten, je nachdem, welche Bibliothek Sie verwenden. Der „Herbstrückzug“-Unklarheit:
- Die Uhren gehen von 2:00 Uhr zurück auf 1:00 Uhr. Die Zeit 1:30 Uhr tritt nun zwei Mal auf. Ohne zusätzlichen Kontext (die Fold-Flag), können Sie nicht erkennen, welche Auftretung gemeint ist.Und DST-Regeln ändern sich. Länder und US-States haben in Erinnerung verändert, abgeschafft oder ihre Regeln geändert. Das Verhalten Ihres Codes hängt davon ab, ob Sie eine aktuelle tzdata-Bibliothek verwenden – das ist eine Operationsfrage, nicht nur eine Entwicklungsfrage.
3. Nicht alle Abweichungen sind ganze Stunden
Indien ist UTC+5:30. Nepal ist UTC+5:45. Teile Australiens sind UTC+9:30. Iran ist in der Winterzeit UTC+3:30 und in der Sommerzeit UTC+4:30. Wenn Ihr System annimmt, dass Zeitzone immer auf der Stunde sind, wird es für Millionen von Benutzern die Zeitstempel schleichend korrupt machen.
4. „Lokale Zeit“ auf einem Server ist sinnlos
Server haben Systemuhren. Diese Uhren haben eine konfigurierte Zeitzone – oft
, manchmal das, was der Hosting-Anbieter standardmäßig eingestellt hat, manchmal das, was ein Sysadmin jahrelang eingestellt hat. Code, der UTCohne eine Zone aufruft, verlässt sich implizit auf diese Serverkonfiguration. Unterschiedliche Umgebungen führen zu unterschiedlichen Ergebnissen. Dies ist ein Fehler, der bei jeder Bereitstellung entstehen kann. new Date() oder datetime.now() Die richtige Herangehensweise, Sprache für Sprache
JavaScript / TypeScript
Das native
Objekt in JavaScript ist eine dünne Wrapper um einen UTC-Millisekunden-Timestamp. Es sieht freundlich aus; es ist es nicht. Vermeiden Sie manuelle Formatierung – verwenden Sie die Date API für die Anzeige oder greifen Sie auf eine Bibliothek zurück. Intl.DateTimeFormat Die moderne Standard ist Temporal
— ein TC39-Vorschlag, der in Chrome 121 eingeführt wurde und in allen Hauptläufen kommt. Es hat erstklassige Unterstützung für Zeitzone und ist die richtige langfristige Lösung: Wenn Sie Temporal noch nicht verwenden können,
// Store an instant (UTC-equivalent)
const meeting = Temporal.Instant.from("2025-06-15T14:00:00Z");
// Display in a specific zone
const nyTime = meeting.toZonedDateTimeISO("America/New_York");
console.log(nyTime.toString()); // 2025-06-15T10:00:00-04:00[America/New_York]
// Convert to Tokyo time
const tokyoTime = meeting.toZonedDateTimeISO("Asia/Tokyo");
console.log(tokyoTime.toString()); // 2025-06-16T23:00:00+09:00[Asia/Tokyo]
date-fns-tz in Kombination mit date-fns ist eine zuverlässige Wahl. Luxon ist eine weitere solide Option. Moment.js ist vollständig, aber nicht mehr gepflegt – migrieren Sie davon. Das Modul unterscheidet zwischen „naiven“ Datumszeiten (keine Zeitzone-Information) und „bewussten“ Datumszeiten (mit tzinfo). Naive Datumszeiten sind ein Fallen – sie sehen wie gültige Zeiten aus, aber tragen keine Bedeutung über Systeme hinweg.
Python
ohne datetime Verwenden Sie immer bewusste Datumszeiten. Verwenden Sie das
Modul zoneinfo (Python 3.9+) für IANA-Zeitzone-Unterstützung: Für Python 3.8 und früher verwenden Sie die
from datetime import datetime
from zoneinfo import ZoneInfo
# Aware datetime — always do this
utc_time = datetime(2025, 6, 15, 14, 0, 0, tzinfo=ZoneInfo("UTC"))
# Convert to New York time
ny_time = utc_time.astimezone(ZoneInfo("America/New_York"))
print(ny_time) # 2025-06-15 10:00:00-04:00
# Never do this — naive datetime, meaningless
bad = datetime(2025, 6, 15, 14, 0, 0) # what zone is this?
Bibliothek – aber achten Sie auf pytz ‘s localize/normalize-API, die Falle hat, pytzvermeidet. zoneinfo Klassen unterstützen IANA-Zonen nativ über
PHP
serialisiert wird. DateTime und DateTimeImmutable . Vorziehen Sie DateTimeZone– es ist sicherer, weil Änderungen neue Objekte zurückgeben statt an Ort und Stelle zu modifizieren. DateTimeImmutable SQL / Datenbanken
$utc = new DateTimeImmutable('2025-06-15T14:00:00', new DateTimeZone('UTC'));
// Convert to Sydney time
$sydney = $utc->setTimezone(new DateTimeZone('Australia/Sydney'));
echo $sydney->format('Y-m-d H:i:s T'); // 2025-06-16 00:00:00 AEST
// Store timestamps as ISO 8601 strings or Unix timestamps
echo $utc->getTimestamp(); // 1749996000
Die Behandlung von Zeitzone in Datenbanken ist eine eigene Minefeld.
PostgreSQL:
- (timestamp with time zone) – es speichert alles als UTC und konvertiert beim Ausgabe. Verwenden Sie nie Verwenden Sie
TIMESTAMPTZ(ohne Zeitzone) für datenorientierte Benutzerinhalte; es speichert das, was Sie geben, ohne Konvertierung.TIMESTAMPMySQL: - Typ ist naiv (keine Zone). Verwenden Sie Der
DATETIMEwenn Sie UTC-Speicherung wünschen, aber beachten Sie, dass sein Bereich auf 2038 begrenzt ist. Für neue Schemata ist es oft sicherer, alsTIMESTAMPin ISO 8601-Format oder als Unix-Timestamp inVARCHARzu speichern.BIGINTSQLite: - Hat keine native Zeitzone-Typ. Speichern Sie als ISO 8601-Text ( ) oder als Unix-Ganzzahl. Behandeln Sie die Konvertierung in Anwendungskode.
2025-06-15T14:00:00ZEgal welche Datenbank Sie verwenden, stellen Sie die Sitzungszeitzone des Servers explizit ein, anstatt auf Standardwerte zu vertrauen.
Praktische Regeln, die tatsächlich funktionieren
Nachdem wir die Theorie durchgearbeitet haben, hier sind die konkreten Regeln, die die meisten Zeitzone-Fehler verhindern:
Speichern Sie immer UTC.
- Jeder Zeitstempel in Ihrer Datenbank sollte UTC sein. Keine Ausnahme für „es wird nur intern verwendet.“ Verwenden Sie IANA-Zonen-Namen, nicht Abweichungen.
- Speichern Sie zusammen mit einem UTC-Timestamp, wenn Sie die ursprüngliche lokale Zeit rekonstruieren müssen. Die Abweichung allein ist nach einer DST-Übergang nicht mehr erreichbar.
America/ChicagoRufen Sie niemals „now“ ohne eine Zone auf. - – geben Sie immer einen expliziten Zeitzone-Argument oder fügen Sie sie sofort hinzu.
datetime.now(),new Date(),time()Konvertieren Sie zum letzten Moment in lokale Zeit. - Führen Sie alle Datumsberechnungen in UTC durch. Konvertieren Sie nur in die lokale Zeit des Benutzers direkt vor der Anzeige. Halten Sie tzdata aktuell.
- Zeitzone-Regeln ändern sich. Machen Sie tzdata-Paket-Updates zu einem Teil Ihrer regelmäßigen Abhängigkeitsverwaltung. Testen Sie um DST-Übergänge.
- Die beiden gefährlichen Tage jedes Jahr (Frühlingssprung, Herbstrückzug) sollten in Ihrem Testset sein, wenn Sie mit Planung oder zeitkritischen Daten arbeiten. Fordern Sie Benutzern explizit ihre Zeitzone an.
- Vertrauen Sie nicht auf IP-Geolokation oder Browser-Schätzung für wichtige Dinge. Zeigen Sie eine Zeitzone-Auswahl; speichern Sie das Ergebnis. Ein Wort zu Unix-Timestamps
Unix-Timestamp – Sekunden seit 1970-01-01T00:00:00Z – sind zeitzone-ungängig definitionsgemäß. Sie sind ein vollkommen gültiger Speicherformat und besonders nützlich in Protokollen, APIs und Caches, wo eine eindeutige Zahl gewünscht ist.
Die Ausnahme: Unix-Timestamps tragen keine ursprüngliche
Absicht des Benutzers . Wenn jemand einen Flug für „Freitagmorgen London-Zeit“ bucht und Sie nur einen Unix-Timestamp speichern, haben Sie die Tatsache verloren, dass sie London meint. Wenn der Flug drei Monate später neu gebucht wird und London in oder aus BST wechselt, können Sie die falsche lokale Zeit anzeigen. Speichern Sie die Zone zusammen mit dem Timestamp, wenn die ursprüngliche Absicht des Benutzers wichtig ist.Das schwierigste Beispiel: Wiederkehrende Ereignisse
Wiederkehrende Ereignisse – wöchentliche Standup-Meetings, monatliche Abrechnungszyklen, tägliche Erinnerungen – zeigen jedes Zeitzone-Randfall gleichzeitig auf.
Stellen Sie sich ein „jeden Montag um 9 Uhr“-Regel für einen Benutzer in Los Angeles vor. Speichern Sie 9 Uhr Pacific? Was passiert, wenn sie nach Tokio reisen? Was passiert, wenn die Uhren im Frühling springen und dieser Montag auf dem Übergangstag fällt?
Die einzige korrekte Modell ist:
Speichern Sie die Wiederholungsregel als Wanduhrzeit + IANA-Zone: „Montag 09:00 America/Los_Angeles“
- Berechnen Sie die nächste UTC-Begegnung bei der Planung, nicht bei der Regel-Erstellung
- Rechnen Sie nach jedem DST-Übergang, der innerhalb des Wiederholungszeitraums fällt
- Bibliotheken wie
(JS) und rrule.js (Python) behandeln dies korrekt, wenn sie die richtige Zeitzone-Information erhalten. Die manuelle Implementierung dieser Logik ist ein zuverlässiger Weg zu feinen Fehlern, die erst Monate später auftauchen. dateutil.rrule Zeitzone sind eine Lüge (und wie man sie in Code behandelt) 2
Erweiterungen installieren
IO-Tools zu Ihrem Lieblingsbrowser hinzufügen für sofortigen Zugriff und schnellere Suche
恵 Die Anzeigetafel ist eingetroffen!
Anzeigetafel ist eine unterhaltsame Möglichkeit, Ihre Spiele zu verfolgen. Alle Daten werden in Ihrem Browser gespeichert. Weitere Funktionen folgen in Kürze!
Unverzichtbare Tools
Alle Neuheiten
AlleAktualisieren: Unser neuestes Werkzeug hinzugefügt am 14. Mai 26
