Wie man Datumsangaben in verschiedenen Zeitzonen formatiert

Datum und Uhrzeit für jede Zeitzone mit der Intl.DateTimeFormat-API von JavaScript anzeigen

Einführung

Der gleiche Zeitpunkt wird weltweit als unterschiedliche Uhrzeit angezeigt. Wenn ein Meeting um 15:00 Uhr in New York beginnt, ist es in London 20:00 Uhr und in Tokio 5:00 Uhr am nächsten Tag. Wenn eine Anwendung Zeiten anzeigt, ohne die Zeitzonen zu berücksichtigen, sehen Nutzer falsche Informationen.

Ein Nutzer in Kalifornien, der einen Flug bucht, der um 14:00 Uhr startet, erwartet, dass auch 14:00 Uhr angezeigt wird. Wenn deine Anwendung jedoch alle Zeiten in der Server-Zeitzone in Virginia formatiert, sieht der Nutzer 17:00 Uhr und kommt drei Stunden zu spät am Flughafen an. Diese Verwirrung zieht sich durch alle Zeitangaben in deiner Anwendung.

Die JavaScript Intl.DateTimeFormat API bietet die timeZone Option, mit der du Datums- und Zeitangaben für jede beliebige Zeitzone formatieren kannst. In dieser Lektion erfährst du, warum es Zeitzonen gibt, wie JavaScript intern damit umgeht und wie du Zeiten korrekt für Nutzer weltweit anzeigst.

Warum es Zeitzonen gibt

Die Erde rotiert und sorgt so dafür, dass Tag und Nacht an verschiedenen Orten zu unterschiedlichen Zeiten auftreten. Wenn die Sonne in New York am höchsten steht, ist sie in London bereits untergegangen und in Tokio noch nicht aufgegangen. Jeder Ort erlebt den Mittag zu einem anderen Zeitpunkt.

Bevor es standardisierte Zeitzonen gab, stellte jede Stadt ihre eigene lokale Zeit nach dem Sonnenstand ein. Das führte zu Problemen für Eisenbahnen und Telegrafen, die weit entfernte Städte verbanden. 1884 einigten sich die Staaten darauf, die Welt in Zeitzonen einzuteilen, die jeweils ungefähr 15 Längengrade breit sind und einer Stunde Erdrotation entsprechen.

Jede Zeitzone hat einen Standardversatz zur koordinierten Weltzeit, abgekürzt UTC. New York verwendet UTC-5 oder UTC-4 – je nachdem, ob Sommerzeit gilt. London verwendet UTC+0 oder UTC+1. In Tokio gilt das ganze Jahr über UTC+9.

Wenn du Uhrzeiten für Nutzer anzeigen möchtest, musst du den universellen Zeitpunkt in die lokale Uhrzeit umwandeln, die sie erwarten.

Wie JavaScript Zeiten intern speichert

JavaScript-Date-Objekte stellen einen einzelnen Zeitpunkt als die Anzahl der Millisekunden seit dem 1. Januar 1970 um Mitternacht UTC dar. Diese interne Darstellung enthält keine Zeitzone.

const date = new Date('2025-03-15T20:00:00Z');
console.log(date.getTime());
// Output: 1742331600000

Das Z am Ende des ISO-Strings zeigt an, dass es sich um UTC-Zeit handelt. Das Date-Objekt speichert den Zeitstempel 1742331600000, der denselben Moment für alle Menschen weltweit darstellt, unabhängig von ihrer Zeitzone.

Wenn du Methoden wie toString() auf einem Date-Objekt aufrufst, wandelt JavaScript den UTC-Zeitstempel automatisch in deine lokale Zeitzone zur Anzeige um. Diese automatische Umwandlung kann zu Verwirrung führen, wenn du Uhrzeiten für eine andere Zeitzone anzeigen möchtest.

Die Intl.DateTimeFormat API mit der Option timeZone gibt dir die volle Kontrolle darüber, welche Zeitzone beim Formatieren verwendet wird.

Die timeZone-Option verwenden

Die Option timeZone legt fest, welche Zeitzone beim Formatieren eines Datums verwendet wird. Gib die Option im Options-Objekt mit, wenn du einen Formatter erstellst.

const date = new Date('2025-03-15T20:00:00Z');

const formatter = new Intl.DateTimeFormat('en-US', {
  timeZone: 'America/New_York',
  dateStyle: 'short',
  timeStyle: 'short'
});

console.log(formatter.format(date));
// Output: "3/15/25, 3:00 PM"

Das Datum steht für 20:00 Uhr UTC. New York ist während der Normalzeit bei UTC-5 oder bei Sommerzeit bei UTC-4. Im März gilt die Sommerzeit, also ist New York bei UTC-4. Der Formatter wandelt 20:00 Uhr UTC in 16:00 Uhr Ortszeit um, aber im Beispiel steht 15:00 Uhr – das deutet darauf hin, dass es in diesem Szenario die Normalzeit ist.

Der Formatter übernimmt die Umwandlung automatisch. Du gibst den UTC-Zeitpunkt und die gewünschte Zeitzone an, und die API liefert dir die korrekte lokale Zeit.

IANA-Zeitzonennamen verstehen

Die Option timeZone akzeptiert Zeitzonen-Bezeichner aus der IANA Time Zone Database. Diese Bezeichner folgen dem Format Region/City, zum Beispiel America/New_York, Europe/London oder Asia/Tokyo.

const date = new Date('2025-03-15T20:00:00Z');

const zones = [
  'America/New_York',
  'Europe/London',
  'Asia/Tokyo',
  'Australia/Sydney'
];

zones.forEach(zone => {
  const formatter = new Intl.DateTimeFormat('en-US', {
    timeZone: zone,
    dateStyle: 'short',
    timeStyle: 'long'
  });

  console.log(`${zone}: ${formatter.format(date)}`);
});

// Output:
// America/New_York: 3/15/25, 4:00:00 PM EDT
// Europe/London: 3/15/25, 8:00:00 PM GMT
// Asia/Tokyo: 3/16/25, 5:00:00 AM JST
// Australia/Sydney: 3/16/25, 7:00:00 AM AEDT

Jede Zeitzone zeigt für denselben Zeitpunkt eine andere lokale Uhrzeit an. In New York ist es am 15. März 16:00 Uhr. In London ist es am 15. März 20:00 Uhr. In Tokio und Sydney ist bereits der 16. März angebrochen – dort ist es 5:00 Uhr bzw. 7:00 Uhr morgens.

IANA-Bezeichner berücksichtigen die Sommerzeit automatisch. Der Formatter weiß, dass America/New_York zwischen Eastern Standard Time und Eastern Daylight Time wechselt und setzt für jedes Datum den korrekten Offset.

Gültige IANA-Zeitzonennamen finden

Die IANA-Datenbank enthält mehrere Hundert Zeitzonen-Bezeichner. Häufige Muster sind:

  • America/New_York für New York City
  • America/Los_Angeles für Los Angeles
  • America/Chicago für Chicago
  • Europe/London für London
  • Europe/Paris für Paris
  • Europe/Berlin für Berlin
  • Asia/Tokyo für Tokio
  • Asia/Shanghai für Shanghai
  • Asia/Kolkata für Indien
  • Australia/Sydney für Sydney
  • Pacific/Auckland für Auckland

Die Bezeichner verwenden Städtenamen statt Zeitzonenabkürzungen wie EST oder PST, da Abkürzungen mehrdeutig sind. EST steht in Nordamerika für Eastern Standard Time, aber auch für Australian Eastern Standard Time. Die namensbasierten Bezeichner sind eindeutig.

Die vollständige Liste der Bezeichner findest du in der Dokumentation der IANA Time Zone Database.

Verwendung von UTC als Zeitzone

Der spezielle Bezeichner UTC formatiert Daten in koordinierter Weltzeit (UTC), die keinen Versatz zum Nullmeridian aufweist.

const date = new Date('2025-03-15T20:00:00Z');

const formatter = new Intl.DateTimeFormat('en-US', {
  timeZone: 'UTC',
  dateStyle: 'short',
  timeStyle: 'long'
});

console.log(formatter.format(date));
// Output: "3/15/25, 8:00:00 PM UTC"

UTC-Zeit entspricht dem internen Zeitstempel, der im Date-Objekt gespeichert ist. Das Verwenden von UTC für Formatierungen ist nützlich, wenn Zeiten angezeigt werden sollen, die sich nicht je nach Standort des Nutzers ändern, z. B. in Server-Logs oder Datenbank-Zeitstempeln.

Bestimmen der Zeitzone des Nutzers

Die Methode resolvedOptions() gibt die tatsächlich vom Formatter verwendeten Optionen zurück, einschließlich der Zeitzone. Wenn du einen Formatter ohne Angabe von timeZone erstellst, wird standardmäßig die Systemzeitzone des Nutzers verwendet.

const formatter = new Intl.DateTimeFormat();
const options = formatter.resolvedOptions();

console.log(options.timeZone);
// Output: "America/New_York" (or user's actual time zone)

Das liefert dir den IANA-Bezeichner für die aktuelle Zeitzone des Nutzers. Du kannst diesen Bezeichner verwenden, um andere Daten in derselben Zeitzone zu formatieren oder um die Zeitzonenpräferenz des Nutzers zu speichern.

const userTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;

const formatter = new Intl.DateTimeFormat('en-US', {
  timeZone: userTimeZone,
  dateStyle: 'full',
  timeStyle: 'long'
});

const date = new Date('2025-03-15T20:00:00Z');
console.log(formatter.format(date));
// Output varies based on user's time zone

Auf diese Weise werden Daten automatisch in der lokalen Zeit des Nutzers angezeigt.

Einen Zeitpunkt für mehrere Zeitzonen formatieren

Du kannst dasselbe Date-Objekt für verschiedene Zeitzonen formatieren, um Nutzern zu zeigen, zu welcher Uhrzeit ein Ereignis an unterschiedlichen Orten stattfindet.

const meetingTime = new Date('2025-03-15T20:00:00Z');

const zones = [
  { name: 'New York', zone: 'America/New_York' },
  { name: 'London', zone: 'Europe/London' },
  { name: 'Tokyo', zone: 'Asia/Tokyo' }
];

zones.forEach(({ name, zone }) => {
  const formatter = new Intl.DateTimeFormat('en-US', {
    timeZone: zone,
    dateStyle: 'long',
    timeStyle: 'short'
  });

  console.log(`${name}: ${formatter.format(meetingTime)}`);
});

// Output:
// New York: March 15, 2025 at 4:00 PM
// London: March 15, 2025 at 8:00 PM
// Tokyo: March 16, 2025 at 5:00 AM

So verstehen Nutzer einfacher, wann ein Meeting oder Ereignis in ihrer und in der Zeitzone anderer Teilnehmer stattfindet.

Daten ohne Uhrzeit über Zeitzonen hinweg formatieren

Beim Formatieren von Daten ohne Uhrzeit kann die Zeitzone beeinflussen, welches Kalenderdatum angezeigt wird. Ein Datum um Mitternacht UTC fällt in verschiedenen Zeitzonen auf unterschiedliche Kalendertage.

const date = new Date('2025-03-16T01:00:00Z');

const formatter1 = new Intl.DateTimeFormat('en-US', {
  timeZone: 'America/Los_Angeles',
  dateStyle: 'long'
});

const formatter2 = new Intl.DateTimeFormat('en-US', {
  timeZone: 'Asia/Tokyo',
  dateStyle: 'long'
});

console.log(`Los Angeles: ${formatter1.format(date)}`);
console.log(`Tokyo: ${formatter2.format(date)}`);

// Output:
// Los Angeles: March 15, 2025
// Tokyo: March 16, 2025

Der Zeitpunkt 1:00 Uhr UTC am 16. März entspricht 17:00 Uhr am 15. März in Los Angeles und 10:00 Uhr am 16. März in Tokio. Das Kalenderdatum unterscheidet sich somit zwischen diesen beiden Zeitzonen um einen Tag.

Das ist wichtig, wenn Termine für geplante Events, Fristen oder andere Daten angezeigt werden, die Nutzer:innen im Bezug auf ihren eigenen Kalender deuten.

Verwendung von Zeitzonen-Offsets

Anstelle von IANA-Bezeichnern kannst du Offset-Strings wie +01:00 oder -05:00 verwenden. Diese stehen für feste Abweichungen von UTC.

const date = new Date('2025-03-15T20:00:00Z');

const formatter = new Intl.DateTimeFormat('en-US', {
  timeZone: '+09:00',
  dateStyle: 'short',
  timeStyle: 'long'
});

console.log(formatter.format(date));
// Output: "3/16/25, 5:00:00 AM GMT+9"

Offset-Strings funktionieren, wenn du die genaue Abweichung kennst, aber nicht den konkreten Ort. Sie berücksichtigen jedoch keine Sommerzeit. Wenn du zum Beispiel -05:00 für New York verwendest, werden die Zeiten während der Sommerzeit falsch angezeigt, da New York dann eigentlich -04:00 benutzt.

IANA-Bezeichner sind zu bevorzugen, da sie die Sommerzeit automatisch berücksichtigen.

Wie die Sommerzeit funktioniert

In vielen Regionen wird die Uhr zweimal im Jahr für die Sommerzeit umgestellt. Im Frühjahr wird eine Stunde vorgestellt, im Herbst eine Stunde zurückgestellt. Dadurch ändert sich der UTC-Offset einer Region im Jahresverlauf.

Wenn du IANA-Zeitzonen-Bezeichner verwendest, berücksichtigt die Intl.DateTimeFormat API automatisch den jeweils richtigen Offset für jedes Datum.

const winterDate = new Date('2025-01-15T20:00:00Z');
const summerDate = new Date('2025-07-15T20:00:00Z');

const formatter = new Intl.DateTimeFormat('en-US', {
  timeZone: 'America/New_York',
  dateStyle: 'long',
  timeStyle: 'long'
});

console.log(`Winter: ${formatter.format(winterDate)}`);
console.log(`Summer: ${formatter.format(summerDate)}`);

// Output:
// Winter: January 15, 2025 at 3:00:00 PM EST
// Summer: July 15, 2025 at 4:00:00 PM EDT

Im Januar verwendet New York die Eastern Standard Time mit einem Offset von UTC-5, angezeigt wird 15:00 Uhr. Im Juli gilt die Eastern Daylight Time mit UTC-4, sodass 16:00 Uhr angezeigt wird. Ein und dieselbe UTC-Zeit ergibt also unterschiedliche lokale Zeiten – abhängig davon, ob die Sommerzeit aktiv ist.

Du musst nicht nachhalten, an welchen Tagen welcher Offset gilt. Die API übernimmt das automatisch.

Uhrzeiten für die Event-Planung formatieren

Wenn du Event-Zeiten anzeigst, formatiere die Zeit sowohl im Ort des Events als auch – optional – im Ort des Nutzers oder der Nutzerin.

const eventTime = new Date('2025-03-15T18:00:00Z');
const eventTimeZone = 'Europe/Paris';
const userTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;

const eventFormatter = new Intl.DateTimeFormat('en-US', {
  timeZone: eventTimeZone,
  dateStyle: 'full',
  timeStyle: 'short'
});

const userFormatter = new Intl.DateTimeFormat('en-US', {
  timeZone: userTimeZone,
  dateStyle: 'full',
  timeStyle: 'short'
});

console.log(`Event time: ${eventFormatter.format(eventTime)} (Paris)`);
console.log(`Your time: ${userFormatter.format(eventTime)}`);

// Output (for a user in New York):
// Event time: Saturday, March 15, 2025 at 7:00 PM (Paris)
// Your time: Saturday, March 15, 2025 at 2:00 PM

Mit diesem Muster sehen Nutzer:innen sowohl, wann das Event in seiner eigenen Zeitzone stattfindet, als auch, wann sie basierend auf ihrem Standort teilnehmen sollten.

Serverzeitstempel in der Zeitzone des Nutzers formatieren

Serverprotokolle und Datenbankeinträge verwenden häufig UTC-Zeitstempel. Beim Anzeigen für Nutzer solltest du diese in die lokale Zeitzone des Nutzers umwandeln.

const serverTimestamp = new Date('2025-03-15T20:00:00Z');
const userTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;

const formatter = new Intl.DateTimeFormat(navigator.language, {
  timeZone: userTimeZone,
  dateStyle: 'short',
  timeStyle: 'medium'
});

console.log(`Activity: ${formatter.format(serverTimestamp)}`);
// Output varies based on user's time zone and locale
// For en-US in New York: "Activity: 3/15/25, 4:00:00 PM"

So sehen Nutzer Zeitstempel immer in ihrer gewohnten Ortszeit statt in UTC oder der Serverzeit.

timeZone mit anderen Optionen kombinieren

Die Option timeZone funktioniert mit allen anderen Optionen von Intl.DateTimeFormat. Du kannst einzelne Datums- und Zeitkomponenten angeben, Stilvorlagen nutzen oder das Kalendersystem steuern.

const date = new Date('2025-03-15T20:00:00Z');

const formatter = new Intl.DateTimeFormat('en-US', {
  timeZone: 'Asia/Tokyo',
  weekday: 'long',
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  hour: 'numeric',
  minute: 'numeric',
  second: 'numeric',
  timeZoneName: 'long'
});

console.log(formatter.format(date));
// Output: "Monday, March 16, 2025 at 5:00:00 AM Japan Standard Time"

Die Option timeZoneName steuert, wie der Name der Zeitzone in der Ausgabe erscheint. In späteren Lektionen gehen wir auf diese Option genauer ein.

Was du vermeiden solltest

Verwende keine Zeitzonenabkürzungen wie EST, PST oder GMT als Werte für die Option timeZone. Solche Abkürzungen sind uneindeutig und werden nicht überall unterstützt.

// Incorrect - abbreviations may not work
const formatter = new Intl.DateTimeFormat('en-US', {
  timeZone: 'EST',  // This may throw an error
  dateStyle: 'short',
  timeStyle: 'short'
});

Setze immer IANA-Kennungen wie America/New_York oder Offset-Strings wie -05:00 ein.

Geh nicht davon aus, dass die Zeitzone des Nutzers der Server-Zeitzone entspricht. Formatiere die Uhrzeiten immer explizit in der richtigen Zeitzone oder verwende die automatisch erkannte Zeitzone des Nutzers.

Formatierer für verschiedene Zeitzonen wiederverwenden

Wenn du Datumsangaben für mehrere Zeitzonen formatierst, werden unter Umständen viele Formatierer erstellt. Wenn du viele Daten mit den gleichen Einstellungen formatierst, solltest du die Formatierer-Instanzen wiederverwenden, um die Performance zu verbessern.

const dates = [
  new Date('2025-03-15T20:00:00Z'),
  new Date('2025-03-16T14:00:00Z'),
  new Date('2025-03-17T09:00:00Z')
];

const formatter = new Intl.DateTimeFormat('en-US', {
  timeZone: 'Europe/Berlin',
  dateStyle: 'short',
  timeStyle: 'short'
});

dates.forEach(date => {
  console.log(formatter.format(date));
});

// Output:
// "3/15/25, 9:00 PM"
// "3/16/25, 3:00 PM"
// "3/17/25, 10:00 AM"

Das Erstellen eines Formatierers umfasst die Verarbeitung von Optionen und das Laden von Lokalisierungsdaten. Wenn du denselben Formatierer für mehrere Daten nutzt, sparst du diesen zusätzlichen Aufwand.