Temporal

Limited availability

This feature is not Baseline because it does not work in some of the most widely-used browsers.

Experimentell: Dies ist eine experimentelle Technologie
Überprüfen Sie die Browser-Kompatibilitätstabelle sorgfältig vor der Verwendung auf produktiven Webseiten.

Das Temporal-Objekt ermöglicht die Verwaltung von Datum und Uhrzeit in verschiedenen Szenarien, einschließlich integrierter Zeitzonen- und Kalenderdarstellung, Wanduhren-Zeitumwandlungen, Arithmetik, Formatierung und mehr. Es ist als vollständiger Ersatz für das Date-Objekt konzipiert.

Beschreibung

Im Gegensatz zu den meisten globalen Objekten ist Temporal kein Konstruktor. Sie können es weder mit dem new Operator verwenden, noch das Temporal-Objekt als Funktion aufrufen. Alle Eigenschaften und Methoden von Temporal sind statisch (genau wie das Math-Objekt).

Temporal verfügt über eine komplexe und leistungsfähige API. Es stellt über 200 nützliche Methoden über mehrere Klassen bereit, was es sehr umfangreich erscheinen lassen kann. Wir werden einen Überblick darüber geben, wie diese APIs miteinander in Beziehung stehen.

Hintergrund und Konzepte

JavaScript verfügt seit seinen frühen Tagen über das Date-Objekt zur Verwaltung von Datum und Uhrzeit. Die Date-API basiert jedoch auf der schlecht gestalteten java.util.Date-Klasse aus Java, die in den frühen 2010er Jahren ersetzt wurde; aber aufgrund des Ziels von JavaScript, die Rückwärtskompatibilität zu wahren, bleibt Date in der Sprache erhalten.

Die wichtige Lektion zum Vorwort der gesamten Einführung ist, dass die Handhabung von Daten komplex ist. Die meisten Probleme von Date können durch das Hinzufügen weiterer Methoden gelöst werden, aber ein grundlegender Designfehler bleibt bestehen: Es bietet so viele Methoden auf demselben Objekt an, dass Entwickler oft verwirrt sind, was sie verwenden sollen, was zu unerwarteten Fallstricken führt. Eine gut gestaltete API muss nicht nur mehr können, sondern sollte auf jeder Abstraktionsebene weniger tun, weil die Verhinderung von Missbrauch genauso wichtig ist wie die Ermöglichung von Anwendungsfällen.

Date-Objekte tragen gleichzeitig zwei Hüte:

  • Als ein Zeitstempel: die Anzahl der Millisekunden oder Nanosekunden, die seit einem festen Zeitpunkt (bekannt als epoch) vergangen sind.
  • Als eine Kombination von Komponenten: Jahr, Monat, Tag, Stunde, Minute, Sekunde, Millisekunde und Nanosekunde. Die Jahr-, Monat- und Tag-Kennungen haben nur im Kontext eines Kalendersystems eine Bedeutung. Die gesamte Kombination wird zu einem einzigartigen Moment in der Geschichte, wenn sie mit einer Zeitzone verbunden ist. Date-Objekte bieten Methoden zum Lesen und Modifizieren dieser Komponenten.

Zeitzonen sind die Ursache für eine beträchtliche Anzahl von datumsbezogenen Fehlern. Bei der Interaktion mit einem Date über das Modell "Kombination aus Komponenten" kann die Uhrzeit nur in zwei Zeitzonen sein: UTC und lokal (Gerät), und es gibt keine Möglichkeit, eine beliebige Zeitzone anzugeben. Auch fehlt das Konzept von „keine Zeitzone“: Dies ist bekannt als ein Kalenderdatum (für Daten) oder eine Wanduhrzeit (für Uhrzeiten), was eine Zeit ist, die Sie „aus einem Kalender oder einer Uhr ablesen“. Wenn Sie beispielsweise einen täglichen Wecker stellen, möchten Sie ihn auf „8:00 Uhr“ einstellen, unabhängig davon, ob Sommerzeit ist oder nicht, ob Sie in eine andere Zeitzone gereist sind usw.

Ein weiteres Merkmal, das Date fehlt, ist ein Kalendersystem. Die meisten Menschen kennen den gregorianischen Kalender, bei dem es zwei Epochen, v. Chr. und n. Chr., gibt; es gibt 12 Monate; jeder Monat hat eine unterschiedliche Anzahl von Tagen; es gibt alle 4 Jahre ein Schaltjahr; und so weiter. Einige dieser Konzepte gelten jedoch möglicherweise nicht, wenn Sie mit einem anderen Kalendersystem arbeiten, wie dem hebräischen Kalender, dem chinesischen Kalender, dem japanischen Kalender usw. Mit Date können Sie nur mit dem gregorianischen Kalendermodell arbeiten.

Es gibt viele andere unerwünschte Altlasten bei Date, wie dass alle Set-Methoden veränderlich sind (was oft unerwünschte Nebeneffekte verursacht), das Datums- und Zeitstring-Format, das nicht auf konsistente Weise analysiert werden kann usw. Letztendlich ist die beste Lösung, eine neue API von Grund auf zu erstellen, was Temporal ist.

API-Übersicht

Temporal ist ein Namensraum, ähnlich wie Intl. Es enthält mehrere Klassen und Namensräume, von denen jeder dazu entwickelt wurde, einen bestimmten Aspekt der Verwaltung von Datum und Uhrzeit zu handhaben. Die Klassen können wie folgt gruppiert werden:

Darüber hinaus gibt es auch einen anderen nützlichen Namensraum, Temporal.Now, der Methoden zum Abrufen der aktuellen Zeit in verschiedenen Formaten bereitstellt.

Gemeinsame Klassenschnittstelle

Es gibt viele Klassen im Temporal-Namensraum, aber sie teilen viele ähnliche Methoden. Die folgende Tabelle listet alle Methoden jeder Klasse auf (außer Konvertierungsmethoden):

Instant ZonedDateTime PlainDateTime PlainDate PlainTime PlainYearMonth PlainMonthDay
Erstellung Instant()
Instant.from()
Instant.fromEpochMilliseconds()
Instant.fromEpochNanoseconds()
ZonedDateTime()
ZonedDateTime.from()
PlainDateTime()
PlainDateTime.from()
PlainDate()
PlainDate.from()
PlainTime()
PlainTime.from()
PlainYearMonth()
PlainYearMonth.from()
PlainMonthDay()
PlainMonthDay.from()
Updater N/A with()
withCalendar()
withTimeZone()
withPlainTime()
with()
withCalendar()
withPlainTime()
with()
withCalendar()
with() with() with()
Arithmetik add()
subtract()
since()
until()
add()
subtract()
since()
until()
add()
subtract()
since()
until()
add()
subtract()
since()
until()
add()
subtract()
since()
until()
add()
subtract()
since()
until()
N/A
Runden round() round() round() N/A round() N/A N/A
Vergleich equals()
Instant.compare()
equals()
ZonedDateTime.compare()
equals()
PlainDateTime.compare()
equals()
PlainDate.compare()
equals()
PlainTime.compare()
equals()
PlainYearMonth.compare()
equals()
Serialisierung toJSON()
toLocaleString()
toString()
valueOf()
toJSON()
toLocaleString()
toString()
valueOf()
toJSON()
toLocaleString()
toString()
valueOf()
toJSON()
toLocaleString()
toString()
valueOf()
toJSON()
toLocaleString()
toString()
valueOf()
toJSON()
toLocaleString()
toString()
valueOf()
toJSON()
toLocaleString()
toString()
valueOf()

Die folgende Tabelle fasst zusammen, welche Eigenschaften in jeder Klasse verfügbar sind, und gibt Ihnen einen Eindruck davon, welche Informationen jede Klasse darstellen kann.

Instant ZonedDateTime PlainDateTime PlainDate PlainTime PlainYearMonth PlainMonthDay
Kalender N/A calendarId calendarId calendarId N/A calendarId calendarId
Jahresbezogen N/A era
eraYear
year
inLeapYear
monthsInYear
daysInYear
era
eraYear
year
inLeapYear
monthsInYear
daysInYear
era
eraYear
year
inLeapYear
monthsInYear
daysInYear
N/A era
eraYear
year
inLeapYear
monthsInYear
daysInYear
N/A
Monatsbezogen N/A month
monthCode
daysInMonth
month
monthCode
daysInMonth
month
monthCode
daysInMonth
N/A month
monthCode
daysInMonth
monthCode
Wochenbezogen N/A weekOfYear
yearOfWeek
daysInWeek
weekOfYear
yearOfWeek
daysInWeek
weekOfYear
yearOfWeek
daysInWeek
N/A N/A N/A
Tagesbezogen N/A day
dayOfWeek
dayOfYear
day
dayOfWeek
dayOfYear
day
dayOfWeek
dayOfYear
N/A N/A day
Zeitkomponenten N/A hour
minute
second
millisecond
microsecond
nanosecond
hour
minute
second
millisecond
microsecond
nanosecond
N/A hour
minute
second
millisecond
microsecond
nanosecond
N/A N/A
Zeitzone N/A timeZoneId
offset
offsetNanoseconds
hoursInDay
getTimeZoneTransition()
startOfDay()
N/A N/A N/A N/A N/A
Epoche-Zeit epochMilliseconds
epochNanoseconds
epochMilliseconds
epochNanoseconds
N/A N/A N/A N/A N/A

Konvertierung zwischen Klassen

Die folgende Tabelle fasst alle Konvertierungsmethoden zusammen, die in jeder Klasse existieren.

Wie konvertiere ich von...
Instant ZonedDateTime PlainDateTime PlainDate PlainTime PlainYearMonth PlainMonthDay
in...Instant/toInstant()Zuerst in ZonedDateTime konvertieren
ZonedDateTimetoZonedDateTimeISO()/toZonedDateTime()toZonedDateTime()PlainDate#toZonedDateTime() (als Argument übergeben)Zuerst in PlainDate konvertieren
PlainDateTimeZuerst in ZonedDateTime konvertierentoPlainDateTime()/toPlainDateTime()PlainDate#toPlainDateTime() (als Argument übergeben)
PlainDatetoPlainDate()toPlainDate()/keine Überlappung der InformationentoPlainDate()toPlainDate()
PlainTimetoPlainTime()toPlainTime()keine Überlappung der Informationen/keine Überlappung der Informationen
PlainYearMonthZuerst in PlainDate konvertierentoPlainYearMonth()keine Überlappung der Informationen/Zuerst in PlainDate konvertieren
PlainMonthDaytoPlainMonthDay()Zuerst in PlainDate konvertieren/

Mit diesen Tabellen sollten Sie eine grundlegende Vorstellung davon haben, wie Sie die Temporal-API navigieren können.

Kalender

Ein Kalender ist eine Möglichkeit, Tage zu organisieren, typischerweise in Perioden von Wochen, Monaten, Jahren und Epochen. Der größte Teil der Welt verwendet den gregorianischen Kalender, aber es gibt viele andere Kalender, die verwendet werden, insbesondere in religiösen und kulturellen Kontexten. Standardmäßig verwenden alle kalenderbewussten Temporal-Objekte das ISO 8601-Kalendersystem, das auf dem gregorianischen Kalender basiert und zusätzliche Wochen-Nummerierungsregeln definiert. Intl.Locale.prototype.getCalendars() listet die meisten Kalender auf, die wahrscheinlich von Browsern unterstützt werden. Hier bieten wir einen kurzen Überblick darüber, wie Kalendersysteme gebildet werden, um Ihnen zu helfen, welche Faktoren zwischen den Kalendern variieren können.

Es gibt drei prominente periodische Ereignisse auf der Erde: ihre Rotation um die Sonne (365,242 Tage für eine Umdrehung), die Rotation des Mondes um die Erde (29,53 Tage von Neumond zu Neumond) und ihre Rotation um ihre Achse (24 Stunden von Sonnenaufgang zu Sonnenaufgang). Jede Kultur hat das gleiche Maß eines "Tages", was 24 Stunden sind. Gelegentliche Änderungen wie die Sommerzeit sind kein Teil des Kalenders, sondern gehören zu den Informationen der Zeitzone.

  • Einige Kalender definieren primär ein Jahr als 365,242 Tage im Durchschnitt, indem sie Jahre mit 365 Tagen definieren und etwa alle 4 Jahre einen zusätzlichen Tag, den Schaltag, hinzufügen. Dann kann das Jahr weiter in Teile namens Monate unterteilt werden. Diese Kalender werden Sonnenkalender genannt. Der gregorianische Kalender und der persische Sonnenkalender sind Sonnenkalender.
  • Einige Kalender definieren primär einen Monat als durchschnittlich 29,5 Tage, indem sie Monate definieren, die abwechselnd 29 und 30 Tage haben. Dann können 12 Monate in einem Jahr von 354 Tagen gruppiert werden. Diese Kalender werden Mondkalender genannt. Der islamische Kalender ist ein Mondkalender. Da ein Mondjahr künstlich ist und nicht mit dem Jahreszeitenzyklus korreliert, sind Mondkalender im Allgemeinen seltener.
  • Einige Kalender definieren auch primär Monate basierend auf Mondzyklen, wie Mondkalender. Dann wird zur Kompensation der 11-Tage-Differenz zum Sonnenjahr etwa alle 3 Jahre ein zusätzlicher Monat, der Schaltmonat, hinzugefügt. Diese Kalender werden lunisolare Kalender genannt. Der hebräische Kalender und der chinesische Kalender sind lunisolare Kalender.

In Temporal wird jedes Datum unter einem Kalendersystem eindeutig durch drei Komponenten identifiziert: year, month und day. year ist eine ganze Zahl, die null oder negativ sein kann und monoton mit der Zeit zunimmt. Das Jahr 1 (oder 0, falls vorhanden) wird als Kalenderepoche bezeichnet und ist für jeden Kalender willkürlich gewählt. month ist eine ganze Zahl, die jedes Mal um 1 zunimmt, beginnend bei 1 und endend bei date.monthsInYear, dann wird sie wieder auf 1 zurückgesetzt, wenn das Jahr fortschreitet. day ist auch eine positive Zahl, muss aber nicht bei 1 beginnen oder jedes Mal um 1 zunehmen, da politische Veränderungen dazu führen können, dass Tage übersprungen oder wiederholt werden. Aber im Allgemeinen erhöht sich day monoton und wird zurückgesetzt, wenn der Monat fortschreitet.

Zusätzlich zu year kann ein Jahr auch eindeutig durch die Kombination von era und eraYear identifiziert werden, für Kalender, die Epochen verwenden. Zum Beispiel verwendet der gregorianische Kalender die Epoche "CE" (Common Era) und "BCE" (Before Common Era), und das Jahr -1 ist dasselbe wie { era: "bce", eraYear: 1 }. era ist ein Kleinbuchstaben-String, und eraYear ist eine willkürliche ganze Zahl, die null oder negativ sein kann oder sogar mit der Zeit abnehmen kann (normalerweise für die älteste Epoche).

Hinweis: Verwenden Sie immer era und eraYear als Paar; verwenden Sie nicht eine Eigenschaft ohne die andere. Um Konflikte zu vermeiden, kombinieren Sie nicht year und era/eraYear, wenn Sie ein Jahr bezeichnen. Wählen Sie eine Jahresdarstellung und verwenden Sie sie konsistent.

Vorsicht vor den folgenden falschen Annahmen über Jahre:

  • Gehen Sie nicht davon aus, dass era und eraYear immer vorhanden sind; sie können undefined sein.
  • Gehen Sie nicht davon aus, dass era eine benutzerfreundliche Zeichenfolge ist; verwenden Sie toLocaleString(), um Ihr Datum zu formatieren.
  • Gehen Sie nicht davon aus, dass zwei year-Werte aus verschiedenen Kalendern vergleichbar sind; verwenden Sie stattdessen die compare()-statische Methode.
  • Nehmen Sie nicht an, dass Jahre 365/366 Tage und 12 Monate haben; verwenden Sie daysInYear und monthsInYear stattdessen.
  • Nehmen Sie nicht an, dass Schaltjahre (inLeapYear ist true) einen zusätzlichen Tag haben; sie können einen zusätzlichen Monat haben.

Zusätzlich zu month kann ein Monat in einem Jahr auch eindeutig durch den monthCode identifiziert werden. monthCode entspricht normalerweise dem Namen des Monats, aber month nicht. Zum Beispiel werden im Fall von lunisolare Kalendern zwei Monate mit demselben monthCode, wobei einer zu einem Schaltjahr gehört und der andere nicht, unterschiedliche month-Werte haben, wenn sie nach dem Schaltmonat kommen, aufgrund der Hinzufügung eines zusätzlichen Monats.

Hinweis: Um Konflikte zu vermeiden, kombinieren Sie nicht month und monthCode, wenn Sie einen Monat bezeichnen. Wählen Sie eine Monatsdarstellung und verwenden Sie sie konsistent. month ist nützlicher, wenn Sie die Reihenfolge der Monate in einem Jahr benötigen (z. B. wenn Sie die Monate durchlaufen), während monthCode nützlicher ist, wenn Sie den Namen des Monats benötigen (z. B. wenn Sie Geburtstage speichern).

Vorsicht vor den folgenden falschen Annahmen über Monate:

  • Gehen Sie nicht davon aus, dass monthCode und month immer übereinstimmen.
  • Gehen Sie nicht von einer bestimmten Anzahl von Tagen in einem Monat aus; verwenden Sie stattdessen daysInMonth.
  • Gehen Sie nicht davon aus, dass monthCode eine benutzerfreundliche Zeichenfolge ist; verwenden Sie toLocaleString(), um Ihr Datum zu formatieren.
  • Im Allgemeinen sollten Sie die Namen der Monate nicht in einem Array oder Objekt zwischenspeichern. Auch wenn monthCode normalerweise innerhalb eines Kalenders auf den Monatsnamen verweist, empfehlen wir, den Monatsnamen immer zu berechnen, indem Sie zum Beispiel date.toLocaleString("en-US", { calendar: date.calendarId, month: "long" }) verwenden.

Zusätzlich zu day (das ein Monatsindex ist), kann ein Tag in einem Jahr auch eindeutig durch dayOfYear identifiziert werden. dayOfYear ist eine positive ganze Zahl, die jedes Mal um 1 zunimmt, beginnend bei 1 und endend bei date.daysInYear.

Das Konzept einer "Woche" ist nicht mit einem astronomischen Ereignis verbunden, sondern ein kulturelles Konstrukt. Daher können Wochen 4, 5, 6, 8 oder mehr Tage haben oder nicht einmal eine feste Anzahl von Tagen. Um die spezifische Anzahl der Tage der Woche eines Datums zu erhalten, verwenden Sie daysInWeek des Datums. Temporal identifiziert Wochen durch die Kombination von weekOfYear und yearOfWeek. weekOfYear ist eine positive ganze Zahl, die jedes Mal um 1 zunimmt, beginnend bei 1, dann wird sie wieder auf 1 zurückgesetzt, wenn das Jahr fortschreitet. yearOfWeek ist normalerweise dasselbe wie year, kann aber am Anfang oder Ende eines jeden Jahres abweichen, da eine Woche zwei Jahre überqueren kann und yearOfWeek eines der beiden Jahre basierend auf den Regeln des Kalenders auswählt.

Hinweis: Verwenden Sie immer weekOfYear und yearOfWeek als Paar; verwenden Sie nicht weekOfYear und year.

Vorsicht vor den folgenden falschen Annahmen über Wochen:

  • Gehen Sie nicht davon aus, dass weekOfYear und yearOfWeek immer vorhanden sind; sie können undefined sein.
  • Gehen Sie nicht davon aus, dass Wochen immer 7 Tage lang sind; verwenden Sie stattdessen daysInWeek.
  • Beachten Sie, dass die aktuelle Temporal-API keine Jahres-Wochen-Daten unterstützt, daher können Sie keine Daten mit diesen Eigenschaften konstruieren oder Daten in Jahres-Wochen-Darstellungen serialisieren. Es handelt sich nur um informative Eigenschaften.

RFC 9557-Format

Alle Temporal-Klassen können mithilfe des in RFC 9557 festgelegten Formats serialisiert und deserialisiert werden, das auf ISO 8601 / RFC 3339 basiert. Das Format in seiner vollständigen Form sieht wie folgt aus (Leerzeichen dienen nur der Lesbarkeit und sollten im eigentlichen String nicht vorhanden sein):

YYYY-MM-DD T HH:mm:ss.sssssssss Z/±HH:mm:ss.sssssssss [time_zone_id] [u-ca=calendar_id]

Verschiedene Klassen haben unterschiedliche Anforderungen an die Anwesenheit jeder Komponente. Daher finden Sie in der Dokumentation jeder Klasse einen Abschnitt mit dem Titel "RFC 9557-Format", der das von dieser Klasse erkannte Format angibt.

Dies ist dem Datums- und Zeitstring-Format ähnlich, das von Date verwendet wird, welches ebenfalls auf ISO 8601 basiert. Die Hauptänderung ist die Möglichkeit, Mikro- und Nanosekundenkomponenten sowie die Zeitzone und das Kalendersystem anzugeben.

Statische Eigenschaften

Temporal.Duration Experimentell

Stellt einen Unterschied zwischen zwei Zeitpunkten dar, der in der Datum/Uhrzeit-Arithmetik verwendet werden kann. Es wird grundsätzlich als Kombination von Jahren, Monaten, Wochen, Tagen, Stunden, Minuten, Sekunden, Millisekunden, Mikrosekunden und Nanosekunden-Werte dargestellt.

Temporal.Instant Experimentell

Stellt einen einzigartigen Punkt in der Geschichte dar, mit Nanosekunden-Genauigkeit. Es wird grundsätzlich als die Anzahl der Nanosekunden seit der Unix-Epoche (Mitternacht zu Beginn des 1. Januar 1970, UTC) ohne Zeitzone oder Kalendersystem dargestellt.

Temporal.Now Experimentell

Bietet Methoden zum Abrufen der aktuellen Zeit in verschiedenen Formaten.

Temporal.PlainDate Experimentell

Stellt ein kalendarisches Datum dar (ein Datum ohne Zeit oder Zeitzone); zum Beispiel ein Ereignis in einem Kalender, das den ganzen Tag über stattfindet, egal in welcher Zeitzone es stattfindet. Es wird grundsätzlich als ISO 8601-Kalenderdatum, mit Jahr-, Monats- und Tagesfeldern und einem zugehörigen Kalendersystem dargestellt.

Temporal.PlainDateTime Experimentell

Stellt ein Datum (Kalenderdatum) und eine Uhrzeit (Wanduhrzeit) ohne Zeitzone dar. Es wird grundlegend als eine Kombination aus einem Datum (mit einem zugehörigen Kalendersystem) und einer Uhrzeit dargestellt.

Temporal.PlainMonthDay Experimentell

Stellt den Monat und den Tag eines kalendarischen Datums dar, ohne Jahr oder Zeitzone; zum Beispiel ein Ereignis in einem Kalender, das jedes Jahr wiederkehrt und den ganzen Tag dauert. Es wird grundsätzlich als ISO 8601-Kalenderdatum, mit Jahr-, Monats- und Tagesfeldern und einem zugehörigen Kalendersystem dargestellt. Das Jahr wird verwendet, um den Monat-Tag in nicht-ISO-Kalendersystemen zu disambiguieren.

Temporal.PlainTime Experimentell

Stellt eine Uhrzeit ohne Datum oder Zeitzone dar; zum Beispiel ein wiederkehrendes Ereignis, das jeden Tag zur selben Zeit stattfindet. Es wird grundlegend als eine Kombination von Stunde, Minute, Sekunde, Millisekunde, Mikrosekunde und Nanosekunde-Werte dargestellt.

Temporal.PlainYearMonth Experimentell

Stellt das Jahr und den Monat eines kalendarischen Datums dar, ohne Tag oder Zeitzone; zum Beispiel ein Ereignis in einem Kalender, das den ganzen Monat über stattfindet. Es wird grundsätzlich als ein ISO 8601-Kalenderdatum, mit Jahr-, Monats- und Tagesfeldern und einem zugehörigen Kalendersystem dargestellt. Der Tag wird verwendet, um das Jahr-Monat in nicht-ISO-Kalendersystemen zu disambiguieren.

Temporal.ZonedDateTime Experimentell

Stellt ein Datum und eine Uhrzeit mit einer Zeitzone dar. Es wird grundsätzlich als eine Kombination aus einem Moment, einer Zeitzone und einem Kalendersystem dargestellt.

Temporal[Symbol.toStringTag]

Der Anfangswert der [Symbol.toStringTag]-Eigenschaft ist der String "Temporal". Diese Eigenschaft wird in Object.prototype.toString() verwendet.

Spezifikationen

Specification
Temporal proposal
# sec-temporal-intro

Browser-Kompatibilität

BCD tables only load in the browser

Siehe auch