← Alle Beiträge

Zeitzonenkorrektes Datumsformat in JavaScript ohne Bibliotheken

Das eingebaute Intl.DateTimeFormat von JavaScript bewältigt IANA-Zeitzonen-Formatierung ohne moment.js oder date-fns. Lerne explizite timeZone-Optionen, sommerzeitsichere Anzeige, formatToParts, die Grenzen der Wanduhr-Umwandlung und wann Temporal oder eine Zeitzonen-Bibliothek noch nützlich ist.

Warum Date keine Zeitzonen-Eigenschaft hat

Ein JavaScript-Date ist immer ein UTC-Millisekundenzähler. Im Objekt ist keine Zeitzone gespeichert. Wenn du .toString() oder .toLocaleString() ohne Optionen aufrufst, nutzt JavaScript die lokale Zeitzone des Runtimes vom Betriebssystem. Derselbe Code erzeugt auf einem Server in New York andere Ausgaben als auf einem Laptop in Tokio, obwohl der zugrunde liegende Timestamp identisch ist.

Mit Intl.DateTimeFormat formatieren

Intl.DateTimeFormat ist die eingebaute API für locale- und zeitzonenbewusstes Formatieren. Sie unterstützt IANA-Zeitzonen-Identifier, behandelt Sommerzeit-Umstellungen automatisch und ist in modernen Browsern und Node.js verfügbar. Der Schlüssel ist, die timeZone-Option explizit zu übergeben, statt sich auf den Runtime-Standard zu verlassen.

  • new Intl.DateTimeFormat('en-US', { timeZone: 'America/New_York', dateStyle: 'full', timeStyle: 'long' }).format(date)
  • date.toLocaleString('en-GB', { timeZone: 'Europe/London', hour12: false })
  • date.toLocaleString('ja-JP', { timeZone: 'Asia/Tokyo' })
  • new Intl.DateTimeFormat('en-US', { timeZone: 'UTC', hour12: false }).format(date)

Einzelne Teile mit formatToParts extrahieren

Nutze formatToParts(), um die einzelnen Datumskomponenten als {type, value}-Objekte für eigene Datums-Strings zu erhalten. Das ist besser, als einen lokalisierten Datums-String zu zerteilen, weil Zeichensetzung, Reihenfolge und Schriften je nach Locale variieren.

  • const parts = new Intl.DateTimeFormat('en-US', { timeZone: 'America/Chicago', year: 'numeric', month: '2-digit', day: '2-digit' }).formatToParts(date)
  • parts.find(p => p.type === 'year').value → '2023'
  • parts.find(p => p.type === 'month').value → '11'
  • Object.fromEntries(parts.map(p => [p.type, p.value])) → { year, month, day, hour, minute, second }

Wanduhrzeit in UTC umwandeln (die schwierige Richtung)

Von einer Wanduhrzeit in einer gegebenen Zeitzone zu UTC zu gelangen ist mit der klassischen Date-API schwieriger. Einen Moment in America/New_York zu formatieren ist einfach; den durch 2026-03-08 02:30 in America/New_York dargestellten Moment zu konstruieren ist es nicht, weil diese lokale Zeit bei Sommerzeit-Umstellungen übersprungen oder wiederholt werden kann.

  • Temporal erreichte 2026 Stufe 4, aber native Browser-Unterstützung ist noch nicht universell
  • Für den Produktionseinsatz in allen Browsern heute sind der Temporal-Polyfill oder date-fns-tz toDate() weiterhin praktische Optionen
  • Vermeide manuelle UTC-Offset-Arithmetik — Sommerzeit-Umstellungen passieren in verschiedenen Jahren zu verschiedenen lokalen Zeiten
  • Das zonedToEpochMs() dieser Seite nutzt eine Offset-Korrektur mit einer Iteration — siehe src/timeUtils.ts

Den richtigen Zeitzonen-Identifier wählen

Nutze IANA-Zeitzonennamen wie America/New_York, Europe/London, Asia/Tokyo oder UTC. Vermeide feste Offsets wie UTC-5 für nutzerseitige Zeiten, denn Offsets ändern sich mit der Sommerzeit. America/New_York kann im Januar UTC-5 und im Juli UTC-4 sein; der IANA-Name lässt die Plattform die korrekte historische Regel für das gewählte Datum anwenden.

  • Gut: America/Los_Angeles — enthält historische und zukünftige Sommerzeit-Regeln
  • Gut: Europe/Berlin — behandelt die mitteleuropäische Sommerzeit automatisch
  • Gut: Asia/Shanghai — stabile UTC+8-Anzeige ohne Sommerzeit
  • Nutze UTC für Logs, API-Speicherung, Datenbank-Timestamps und regionenübergreifenden Vergleich
  • Nutze die IANA-Zeitzone des Nutzers für die finale Anzeige in der Produkt-UI

FAQ zur Zeitzonen-Formatierung

Two daylight-saving transitions a year break the assumption that "wall-clock time + timezone = a unique moment". Both are encoded in the IANA timezone database (still often called the Olson database) — the authoritative source of timezone rules used by every modern OS, browser, and language runtime.

  • DST gap: 02:00 to 02:59 local time does not exist on the spring-forward day
  • DST overlap: 01:00 to 01:59 local time occurs twice on the fall-back day
  • Ambiguous local time: in the overlap window you must pick "earlier" or "later" explicitly
  • Python uses a fold flag; JS Temporal uses a disambiguation option; java.time defaults to the earlier offset
  • Olson database / IANA tzdata / zoneinfo are three names for the same dataset, updated several times a year
  • Each IANA name (America/Los_Angeles, Europe/Berlin) maps to a list of (transition, offset, abbreviation) tuples
  • Stale tzdata on a device produces silently-wrong local times after any DST or zone change
  • Server best practice: do all date arithmetic in UTC, convert to local only at display

FAQ

Can JavaScript format a date in another timezone without a library?
Yes. Use Intl.DateTimeFormat or toLocaleString with a timeZone option, such as America/New_York or Asia/Tokyo.
Does Intl.DateTimeFormat handle daylight saving time?
Yes. When you use an IANA timezone identifier, the runtime applies the correct offset for that timezone and date.
Should I store timezone offsets or timezone names?
Store UTC for event instants. If you need the user's local context, store an IANA timezone name such as America/New_York, not only a numeric offset.
How do I get the user's timezone in JavaScript?
Use Intl.DateTimeFormat().resolvedOptions().timeZone, which returns an IANA name like America/New_York. Store that name, not a numeric offset, when you need to reconstruct the user's local time later.
What is the DST gap (spring-forward)?
The DST gap is the wall-clock hour that is skipped when daylight saving time begins. In most US zones, when the clock would tick from 02:00 to 02:59 it instead jumps to 03:00. Local times in that window do not exist on the transition day. Unix timestamps themselves never skip; only the wall-clock interpretation does.
What is the DST overlap (fall-back)?
The DST overlap is the wall-clock hour that occurs twice when daylight saving time ends. In most US zones, the clock ticks from 01:59 back to 01:00, so every minute from 01:00 to 01:59 happens twice. A wall-clock time in that window maps to two Unix timestamps; converters and schedulers must specify "earlier" or "later".