Zeitzonen in Software speichern und verwalten

Entwickler
time-zonesdevelopment

Zeitzonenfehler gehören zu den heimtückischsten in der Softwareentwicklung. Ein Meeting, das als „UTC−5” gespeichert wird, zeigt heute die richtige Zeit – und verschiebt sich dann lautlos um eine Stunde, wenn die Sommerzeit beginnt. Die Lösung ist unkompliziert, sobald man weiß, welche Schicht was übernimmt.

Niemals rohe UTC-Offsets speichern

Ein Offset wie −5 oder +05:30 ist eine Momentaufnahme der aktuellen Differenz zu UTC – er sagt nichts darüber aus, wie der Offset im März oder nach einer Gesetzesänderung aussehen wird. UTC−5 für „New Yorker Zeit” zu speichern zeigt für die Hälfte des Jahres die falsche Zeit.

Das nicht tun:

meeting_time: "2026-03-10T14:00:00-05:00"
user_timezone: "UTC-5"

IANA-Zeitzonennamen speichern

Die IANA Time Zone Database (America/New_York, Europe/London, Asia/Kolkata) enthält den vollständigen Regelsatz für eine Region – einschließlich aller vergangenen und zukünftigen Sommerzeitumstellungen. Alle wichtigen Sprachen und Laufzeitumgebungen liefern sie mit.

Stattdessen so vorgehen:

meeting_time_utc: "2026-03-10T19:00:00Z"   // Zeitpunkt, immer UTC
user_timezone: "America/New_York"            // Regelset für die Anzeige

Speichere den Zeitpunkt in UTC, speichere den IANA-Namen des Nutzers separat, und leite die lokale Anzeigezeit zur Darstellungszeit ab.

Die zeitzonen-bewussten APIs der Plattform verwenden

Die meisten Laufzeitumgebungen bieten eine zeitzonenbewusste API, die IANA-Namen akzeptiert. Bevorzuge diese gegenüber manueller Offset-Arithmetik.

JavaScript / TypeScript:

const formatter = new Intl.DateTimeFormat("en-US", {
  timeZone: "America/New_York",
  dateStyle: "full",
  timeStyle: "short",
});
formatter.format(new Date("2026-03-10T19:00:00Z"));
// → "Tuesday, March 10, 2026 at 3:00 PM"

Python:

from zoneinfo import ZoneInfo  # Python 3.9+
from datetime import datetime

utc_dt = datetime(2026, 3, 10, 19, 0, tzinfo=ZoneInfo("UTC"))
ny_dt = utc_dt.astimezone(ZoneInfo("America/New_York"))
# → 2026-03-10 15:00:00-04:00 (EDT, not EST)

PostgreSQL:

-- Store as timestamptz (UTC internally), display with AT TIME ZONE
SELECT meeting_at AT TIME ZONE 'America/New_York' FROM meetings;

IANA-Namen aus Nutzereingaben validieren

Wenn Nutzer ihre Zeitzone eingeben oder auswählen können, validiere den Wert gegen die IANA-Datenbank, bevor du ihn speicherst. Ungültige oder veraltete Namen (US/Eastern statt America/New_York) können sich auf verschiedenen Plattformen unterschiedlich verhalten.

JavaScript:

function isValidIANA(tz: string): boolean {
  try {
    Intl.DateTimeFormat(undefined, { timeZone: tz });
    return true;
  } catch {
    return false;
  }
}

Die IANA-Datenbank aktuell halten

Die IANA-Datenbank wird mehrmals im Jahr aktualisiert, wenn Regierungen ihre Sommerzeitregeln ändern. Betriebssysteme und Laufzeitumgebungen liefern Updates – halte sie aktuell, besonders für Serverumgebungen, die nicht automatisch aktualisieren.

Für Node.js-Projekte bündeln die Pakete @js-joda/timezone oder luxon ihre eigene Kopie der IANA-Daten unabhängig vom Betriebssystem.

Kurz-Checkliste

  • Nutzerzeitzone als IANA-Namen speichern (America/Chicago), nicht als Offset (UTC−6)
  • Zeitpunkte als UTC-Zeitstempel speichern
  • Zur Darstellungszeit in Ortszeit umrechnen, nicht zur Speicherzeit
  • Plattformeigene APIs verwenden, die IANA-Namen akzeptieren
  • IANA-Namen aus Nutzereingaben vor dem Speichern validieren
Buy me a coffe