Herzlich willkommen zum SELF-Treffen 2026
vom 24.04. – 26.04.2026
in Halle (Saale)
Temporal
Das Temporal API ist dazu gedacht, das Date-Objekt durch eine Familie anderer Objekte zu ersetzen, die besser mit Zeitzonen, nicht-gregorianischen Kalendern und Zeitdifferenzen umgehen können. Eine Erweiterung von Date um entsprechende Funktionen wurde nicht als sinnvoll erachtet. Statt dessen ging man den gleichen Weg wie Java, wo in Version 8 die Date- und Time-Klassen aus java.util durch ein neues java.time Package abgelöst wurden.
Die Objekte des Temporal API sind ähnlich benannt, im Detail aber anders aufgebaut. Die Implementierung in den Browsern ist noch nicht abgeschlossen, bitte prüfe vor der Verwendung zunächst die Kompatibilitätsangaben.
Einen browsergeeigneten Polyfill gibt es von FullCalendar unter der Adresse https://cdn.jsdelivr.net/npm/temporal-polyfill@0.3.0/global.min.js. Aus Datenschutzgründen bitte nie von dort in deine Seite einbinden, sondern herunterladen und selbst hosten!
Inhaltsverzeichnis
Die Temporal-Klassen
Hier zunächst ein schneller Wegweiser zu den einzelnen Temporal-Klassen.
Einführung
Die Grundlage des Temporal API ist die Klasse Temporal.Instant, die einen bestimmten Zeitpunkt beschreibt. Offiziell ist dieser Zeitpunkt frei von Kalender- oder Zeitzoneninformationen, praktisch ist ein Instant aber genau wie Date auf die Unix-Epoche (01.01.1970, Mitternacht) bezogen und wird durch die Nanosekunden beschrieben, die seitdem vergangen sind (oder bis dahin vergehen müssen).
Um zu bestimmen, welchem Datum oder welcher Zeit ein Instant entspricht, muss er mit einer Zeitzone und einem Kalender kombiniert werden. Dazu besitzt das Instant-Objekt die Methode toZonedDateTimeISO(), die eine Zeitzonenangabe (entweder ein Kürzel wie CET oder eine Ortsangabe wie Europe/Berlin) erwartet und den Instant in dieser Zeitzone auf Basis des ISO-8601 Kalenders (gregorianisch) darstellt. Das Ergebnis ist ein Temporal.ZonedDateTime-Objekt. Die Umrechnung in andere Kalendersysteme ist möglich, erfordert aber den Aufruf einer der with...-Methoden des ZonedDateTime-Objekts.
Um Zeitdifferenzen zu beschreiben, wurde die Klasse Temporal.Duration eingeführt. Sie beschreibt eine Zeitdauer in Kalenderbegriffen (z.B. Jahre, Tage, Stunden oder Sekunden), ist aber nicht auf einen bestimmtem Kalender ausgerichtet. Dieser Bezug wird hergestellt, wenn eine Duration verwendet wird, um eine kalenderbezogene Datums- oder Zeitangabe zu verändern.
Darüber hinaus gibt es eine Gruppe von Klassen, die zwar kalenderbasierend sind, aber weder Zeitzonen noch Zeitumstellungen beachten. Dies sind: PlainDate (nur Datum), PlainTime (Zeit ohne Datum), PlainDateTime (die Kombination von beiden) sowie PlainMonthDay (nur Monat und Tag) und PlainYearMonth (nur Jahr und Monat). Letztere eignen sich vor allem zur Darstellung von Aussagen wie „Am 24.12. ist Weihnachten“ oder „Im Juli 2026 verreisen wir“.
Außerdem gibt es die Helferklasse Temporal.Now, die fünf Methoden zum Abruf des aktuellen Moments in unterschiedlichen Repräsentationen (Instant, PlainDate, PlainDateTime, PlainTime und ZonedDateTime) sowie die Abfrage der Zeitzone des Computers ermöglicht.
Vorteile der Temporal-Klassen
- Ein
Date-Objekt kann über set-Methoden verändert werden, was böse Überraschungen auslösen kann. Die Temporal-Objekte sind hingegen unveränderlich. Wenn ich zu einem ZonedDateTime-Objekt eine Stunde addiere, bekomme ich ein neues Objekt, ähnlich wie beiDateTimeImmutablein PHP. - Der Januar ist Monat 0? Nicht bei Temporal, hier werden die Monate so, wie man es erwartet, ab 1 nummeriert.
- Zeitzonen können mit Hilfe der aus PHP bekannten Zeitzonenbezeichnungen angegeben werden. Entweder als Kürzel (CET=Central European Time) oder als Ortsbezeichnung der IANA Zeitzonendatenbank (Europe/Berlin).
Instant, Plain oder Zoned?
Die Vielzahl der verfügbaren Klassen erfordert die Entscheidung, welche Klasse für einen bestimmten Zweck die richtige ist.
- Die Instant-Klasse beschreibt einen Zeitpunkt, ohne Bezug zu einem Kalender. Man kann Instants nicht sinnvoll ausgeben (außer als Nanosekunden seit dem 01.01.1970), aber vergleichen, Differenzen bilden (in Nanosekunden), und sie durch Angabe einer Zeitzone auch in ein ZonedDateTime-Objekte umrechnen.
- Die PlainDate-Klasse enthält weder eine Zeit noch eine Zeitzone. Sie repräsentiert ein Datum in dem zugeordneten Kalender und kann damit für alle Anlässe verwendet werden, wo die Zeit irrelevant ist. Wenn ich berechnen will, welches Datum in 5 Tagen ist, muss ich mich nicht darum kümmern, ob dazwischen vielleicht die Sommerzeit begonnen hat und ich deshalb 60 Minuten extra addieren muss.
- Mit PlainTime erhält man ein Objekt, das nur die Uhrzeit speichert, unabhängig vom Datum und unabhängig von Zeitumstellungen.
- Die Klasse PlainDateTime kombiniert PlainDate und PlainTime zu einem Zeitpunkt, der aber immer noch unabhängig von Zeitzonen ist. Für Zeitpunkte der lokalen Zeit geeignet.
- Für Zeitangaben der realen Welt, für die ein Kalender und eine Zeitzone von bedeutung ist, verwendet man ZonedDateTime.
Gemeinsame Konzepte
Kalender
Temporal unterstützt die Kalender, deren IDs von Intl.supportedValuesOf('calendar') zurückgegeben werden. Teils kann die Kalender-ID bei der Objektkonstruktion angegeben werden, teils muss zunächst der ISO 8601-Kalender (was im Wesentlichen dem gregorianischen Kalender entspricht) verwendet und dann auf den gewünschten Kalender umgestellt werden.
Stringformat für die Erzeugung von Temporal-Objekten
Hauptartikel: Stringdarstellung von Temporal-Objekten
Temporal-Objekte können unter anderem aus geeignet aufgebauten Strings erstellt werden. Das Format dieser Strings basiert auf der ISO 8601-Norm und sieht im Maximalfall so aus:
YYYY-MM-DD T HH:mm:SS.sssssssss +HH:mm [zeitzone] [u-ca=kalender] Datum Uhrzeit Offset
Die Leerstellen dienen der Lesbarkeit und müssen im praktischen Einsatz weggelassen werden.
Je nachdem, welches Objekt erzeugt werden soll, sind einige dieser Komponenten erforderlich oder werden ignoriert. Hier nur einige Beispiele, eine genauere Beschreibung steht im Hauptartikel.
| String | Bedeutung |
|---|---|
| 2026-02-27 | 27. Februar 2026 |
| 2026-02-27T12:00 | 27. Februar 2026, 12:00 Uhr. Ortzeit. Wo auch immer. |
| 20260227T1200 | Gleicher Zeitpunkt. - und : sind optional |
| 2026-02-27T12:00+02:00 | 12:00 Mittags in Osteuropa. Oder in Ägypten. Oder Südafrika. |
| 2026-05-27T12:00+02:00 | Im Mai könnte es auch Berlin sein. Oder Südafrika... |
| 2026-05-27T12:00[Europe/Berlin] | Mit Zeitzone wird es klarer. |
| 2026-05 | Mai 2026, für ein PlainYearMonth Objekt |
| 12-24 | Weihnachten. Jedes Jahr. |
| 2027-02-07[Asia/Riyadh][u-ca-islamic] | 1. Ramadan 1448 (ISO-Jahr 2026) |
Um das Datum aus dem letzten Beispiel korrekt auszugeben, muss man ‐ zumindest auf einem auf de-DE eingestellten Computer, etwas Tipparbeit leisten:
const datum = Temporal.ZonedDateTime.from("2027-02-07[Asia/Riyadh][u-ca=islamic]");
console.log("de-DE Datum in Riad: "
+ datum.toLocaleString("de-DE-u-ca-islamic", { dateStyle: 'long' }));
// '1. Ramadan 1448 AH'
console.log("ar-DE Datum in Riad: "
+ datum.toLocaleString("ar-DE-u-ca-islamic", { dateStyle: 'long' }));
// '1 رمضان 1448 هـ'
console.log("ar-SA Datum in Riad: "
+ datum.toLocaleString("de-SA-u-ca-islamic", { dateStyle: 'long' }));
// '١ رمضان ١٤٤٨ هـ'
ar ist der Sprachcode für arabisch, und SA der Regionscode für Saudi-Arabien.
Runden
Temporal-Objekte, die eine Zeitkomponente enthalten (Instant, PlainTime, PlainDateTime, ZonedDateTime und Duration) verfügen über eine Methode namens round(). Diese Methode erwartet als Argument entweder eine Zeichenkette oder ein Optionsobjekt; bei Übergabe einer Zeichenkette wird diese als smallestUnit eines Optionsobjekts interpretiert.
In dem Optionsobjekt können drei Eigenschaften (bei Duration: fünf) angegeben werden:
-
smallestUnit(String, erforderlich) -
- Auf welche Zeitstufe soll gerundet werden. Mögliche Angaben sind
"nanosecond","microsecond","millisecond","second","minute"und"hour" - Bei PlainDateTime und ZonedDateTime ist zusätzlich
"day"möglich - Bei Duration ist zusätzlich
"day","week","month"und"year"erlaubt - Die Pluralformen dieser Begriffe sind erlaubte Synonyme.
- Auf welche Zeitstufe soll gerundet werden. Mögliche Angaben sind
-
roundingMode(String, optional) -
Welche Rundungsregel soll verwendet werden. Die erlaubten Angaben entsprechen dem
roundingModein Intl.NumberFormat(). Der Defaultwert ist"halfExpand", was dem kaufmännischen Runden entspricht. -
roundingIncrement(positive Ganzzahl, optional) -
Die Rundung erfolgt auf ein Vielfaches des roundingIncrement. Der Standardwert ist 1, aber wenn man die Sekunden auf Zehnerschritte runden möchte, kann man hier auch eine 10 angeben.
-
Ausnahme: Soll ein PlainDateTime oder ZonedDateTime auf Tage gerundet werden, ist nur 1 als Inkrement möglich.
Eine Duration kann mit beliebigem Inkrement auf Tage gerundet werden. - Beachte: Das Inkrement muss ein Teiler für den Maximalwert der gewählten Zeitstufe sein. Genauer gesagt: für den Maximalwert plus 1 – bei einer Rundung auf Stunden muss 24 durch das Inkrement teilbar sein, bei Minuten oder Sekunden muss 60 teilbar sein.
Bei Instant-Objekten ist es etwas anders, hier muss die Anzahl der Rundungseinheiten pro Tag durch das Inkrement teilbar sein, also 24 Stunden, 1440 Minuten oder 86400 Sekunden.
Für das Runden von Duration-Objekten sind zwei weitere Optionseinträge möglich:
-
relativeTo(Temporal-Objekt mit Kalender oder RFC 9557-String mit Datum und ggf. Kalender) -
Wenn ein Duration-Objekt einen Kalender-Anteil besitzt (Tag, Woche, Monat, Jahr), ist diese Option erforderlich, andernfalls optional. Die relativeTo-Angabe wird benötigt, um die erforderlichen Kalenderinformationen für die Rundung beizusteuern.
- Beachte: Wenn relativeTo erforderlich ist, aber fehlt, kann die Fehlermeldung im Browser irreführend sein („largestUnit when rounding Duration was not the largest provided unit“).
-
largestUnit(String, optional) -
Die größte, zu verwendende Einheit in der gerundeten Duration (siehe
smallestUnitfür die möglichen Werte). Enthält die zu rundende Duration größere Einheiten, werden sie die angegebenelargestUnitumgerechnet. Beispiel: Runden von "PT5M10.4S" mit largestUnit "seconds" ergibt 310 Sekunden, nicht 5 Minuten und 10 Sekunden. Allerdings darflargestUnitkeine kleinere Einheit alssmallestUnitsein.
const jetzt = Temporal.Now.plainDateTimeISO();
// Annahme: Es ist '2026-03-03T15:13:06.445'
console.log("%s", jetzt.round("minutes"));
// ergibt '2026-03-03T15:13:00'
console.log("%s", jetzt.round({ roundingIncrement: 5, smallestUnit: "seconds"));
// ergibt '2026-03-03T15:13:05'
console.log("%s", Temporal.Duration.from("PT10H20M15.3S")
.round({ smallestUnit: "seconds", largestUnit: "minutes"}));
// ergibt 'PT620M15S'
console.log(jetzt.round({ roundingIncrement: 7, smallestUnit: "minutes").toString());
// Temporal error: dividend is not divisible by roundingIncrement
Eine Erklärung zu console.log("%s"...) findest Du beim Console-API.
Erzeugung
Die Spezifikation beschreibt Konstruktoraufrufe für alle Temporal-Klassen, die Implementierung ist aber unvollständig. Deshalb ist new noch nicht einsetzbar.
Statt dessen verfügen alle Temporal-Klassen über eine statische from-Methode, die je nach Klasse mit unterschiedlichen Parametern aufrufbar ist. Diese Methode wird auf den Detailseiten zu den jeweiligen Klassen beschrieben.
Umwandeln
Alle Temporal-Objekte verfügen über Methoden, mit denen sie sich in andere Darstellungen konvertieren lassen:
toLocaleString()
Bitte beachte vor dem Einsatz die Kompatibilität.
Sofern der Computer des Anwenders das Intl.DateTimeFormat unterstützt, delegiert toLocaleString() seine Aufgabe an dieses API. Andernfalls (was de facto nicht vorkommt) fällt toLocaleString auf toString() zurück, unter Verwendung des Standard-Locale und von Default-Optionen.
Syntax:
toLocaleString( locales, options )
Die Parameter entsprechen denen von new Intl.DateTimeFormat(...).
toLocaleString() erzeugt intern ein Intl.DateTimeFormat-Objekt und das ist ein aufwändiger Vorgang. Wenn eine größere Anzahl von Temporal-Werten in einen Locale-String konvertiert werden muss, ist es besser, dieses Objekt vorab selbst zu erzeugen und die Temporal-Objekte an dessen format()-Methode zu übergeben.toString()
Bitte beachte vor dem Einsatz die Kompatibilität.
Die toString()-Methode generiert eine RFC 9557-Darstellung des Temporal-Objekts. Über ein Options-Objekt lässt sich die Form der Darstellung etwas beeinflussen.
Syntax:
toLocaleString( options )
const jetzt = Temporal.Instant.zonedDateTimeISO();
const ortszeit = jetzt.toString( {
smallestUnit: "minutes",
timeZoneName: "never",
offset: "never" } );
console.log(`Ortszeit ist ${ortszeit}`);
// Ausgabe z.B.: Ortszeit ist 2026-03-23T12:05
Das options Objekt ist optional. Fehlt es, werden für alle Optionen die Defaultwerte verwendet. Es handelt sich hierbei um ein normales JavaScript-Objekt, in dem von toString() folgende Eigenschaften beachtet werden:
- calendarName
- (nicht für Duration)
- Gibt an, ob der RFC 9557-String eine Kalenderangabe
[u-ca=calendar_id]enthalten soll. Mögliche Werte sind"auto"(Default),"always","never"und"critical". -
"always"und"never"sollten selbsterklärend sein,"auto"bedeutet, dass die Kalenderangabe eingefügt wird, wenn ein anderer Kalender als iso8601 verwendet wird."critical"entspricht"always", fügt aber das Critical-Flag hinzu (siehe unten). - timeZoneName
- (nur bei Temporal-Objekten mit Zeitzone)
- Gibt an, dass der Name der Zeitzone (z. B.
[Europe/Berlin]) ausgegeben werden soll. - Mögliche Werte sind
"auto"(Default), was den Namen immer ausgibt,"never"und"critical"."critical"entspricht"auto", fügt aber das Critical-Flag hinzu (siehe unten). - offset
- (nur bei Temporal-Objekten mit Zeitzone)
- Gibt an, ob der Zeitzonenoffset (
±HH:mm) mit ausgegeben werden soll. - Mögliche Werte sind
"auto"(default), was ihn immer ausgibt, oder"never". - fractionalSecondDigits
- (nur bei Temporal-Objekten mit Zeitanteil)
- Entweder
"auto"(Default), oder eine Ganzzahl von 0 bis 9. Gibt an, mit wievielen Stellen die Sekundenbruchteile dargestellt werden sollen. Dazu wird je nach Bedarf gerundet oder mit Nullen aufgefüllt. Bei"auto"werden gerade soviele Stellen verwendet, wie nötig sind. - roundingMode
- (nur bei Temporal-Objekten mit Zeitanteil)
- Entspricht dem roundingMode von Intl.NumberFormat und gibt an, wie die Sekundenbruchteile gerundet werden sollen. Default ist
"trunc". - smallestUnit
- (nur bei Temporal-Objekten mit Zeitanteil)
- Wird diese Option angegeben, überschreibt sie fractionalSecondDigits. Der Default ist dementsprechend, die fractionalSecondDigits-Angabe zu verwenden.
- Mögliche Werte sind
"minute","second","millisecond","microsecond"und"nanosecond", beziehungsweise deren Pluralformen. Mit"minute"werden die Sekunden weggelassen, die anderen Angaben entsprechen den Werten 0, 3, 6 und 9 bei fractionalSecondDigits.
Und was ist nun critical? Laut RFC 9557 kann der Empfänger eines DateTime-Strings Teile des Strings ignorieren, wenn nicht alles zusammen passt. 2026-03-24T17:25:10 +02:00[Europe/Berlin] wäre so ein Fall, am 24. März 2026 war der Timezone-Offset für Berlin noch +01:00. Es könnte auch sein, dass eine unbekannte Zeitzone angegeben wird oder ein Kalendername, der vom Empfänger nicht unterstützt wird. Steht direkt hinter der öffnenden eckigen Klammer ein Ausrufezeichen (z. B. [!Europe/Köln]), darf diese Angabe nicht ignoriert werden, der DateTime-String muss als fehlerhaft zurückgewiesen werden. Die from-Methoden der Temporal-Objekte sind allerdings „überkritisch“, sie werfen bei einer unbekannten oder inkonsistenten Angabe immer einen Error.
toJSON
Diese Methode erzeugt eine String-Darstellung des Objekts, mit der sich das Temporal-Objekt wiederherstellen lässt. Näheres im Abschnitt zu [#Temporal und JSON|JSON].
Temporal.PlainDate
Ein PlainDate-Objekt kann auf unterschiedliche Arten erzeugt werden:
- Mittels new Temporal.PlainDate(jahr,monat,tag,kalender) – bislang nur im Firefox. Die Angabe der Kalender-ID ist optional, Default ist der ISO 8601-Kalender.
// Aus einem ISO-String
const ostern1 = Temporal.PlainDate.from("2026-04-05");
// Aus einem Objekt mit den Einzelwerten
const ostern2 = Temporal.PlainDate.from({ year: 2026, month: 4, day: 5 });
// Mit Hilfe des Konstruktors, ähnlich wie Date, aber mit "richtigem" Monat
const ostern3 = new Temporal.PlainDate(2026, 4, 5);
// Das heutige Datum
const heute = Temporal.Now.plainDateISO();
// Ausgeben
console.log(heute.toString()); // Als ISO-String YYYY-MM-DD (2026-02-24)
console.log(heute.toLocaleString()); // Passend zum Default-Locale (24.2.2026)
console.log(heute.toLocaleString("en-US")); // Mit bestimmtem Locale (2/24/2026)
Die einzelnen Komponenten eines PlainDate (year, month, day, etc) sind über Eigenschaften verfügbar, dazu auch abgeleitete Werte wie Wochentag (dayOfWeek), Tagesnummer im Jahr (dayOfYear), Kalenderwoche (weekOfYear) und Kontextinformationen wie Tage im Monat (daysInMonth), Tage im Jahr (daysInYear) und ob ein Schaltjahr vorliegt (inLeapYear).
Diese Eigenschaften können nur gelesen werden, weil Temporal-Objekte unveränderlich sind. Man kann aber eine modifizierte Kopie erstellen, dazu dient die with-Methode. Man übergibt ihr ein Objekt mit den Komponenten, die geändert werden sollen. Bei einem PlainDate sind das vor allem year, month und day:
const datum = Temporal.PlainDate.from("2026-05-01");
const eom = datum.with( { day: datum.daysInMonth } );
Siehe auch
- MDN: Temporal Standardobjekt (automatisch übersetzt)