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
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. Eine genaue Beschreibung des [[./Stringdarstellung|Temporal-Stringformats]] haben wir in einen eigenen Artikel verlegt. Hier nur einige Beispiele:
| 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 das Sprachkürzel für arabisch, und SA das Regionskürzel 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.</p>
-
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.
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)