Temporal
Limited availability
Cette fonctionnalité n'est pas Compatible car elle ne fonctionne pas dans certains des navigateurs les plus utilisés.
L'objet Temporal permet la gestion des dates et heures dans divers scénarios, y compris la représentation intégrée des fuseaux horaires et des calendriers, les conversions d'heures murales, les opérations arithmétiques, le formatage, et plus encore. Il est conçu comme un remplacement complet de l'objet Date.
Description
Contrairement à la plupart des objets globaux, Temporal n'est pas un constructeur. Vous ne pouvez pas utiliser l'opérateur new ni invoquer l'objet Temporal comme une fonction. Toutes les propriétés et méthodes de Temporal sont statiques (comme pour l'objet Math).
Temporal possède une API complexe et puissante. Il expose plus de 200 méthodes utilitaires par l'intermédiaire de plusieurs classes, ce qui peut sembler très complexe. Nous proposons un aperçu général de la façon dont ces API sont liées entre elles.
Contexte et concepts
JavaScript dispose de l'objet Date pour gérer les dates et les heures depuis ses débuts. Cependant, l'API Date est basée sur la classe java.util.Date mal conçue de Java, remplacée au début des années 2010 ; mais, en raison de l'objectif de compatibilité ascendante de JavaScript, Date est restée dans le langage.
La leçon importante à prefacer l'ensemble de cette introduction est que la gestion des dates est complexe. La plupart des problèmes de Date peuvent être corrigés en ajoutant des méthodes, mais un défaut fondamental de conception subsiste : il expose tellement de méthodes sur le même objet que les développeur·euse·s sont souvent confus·e·s quant à ce qu'il faut utiliser, ce qui conduit à des pièges inattendus. Une API bien conçue doit non seulement faire plus, mais aussi faire moins à chaque niveau d'abstraction, car prévenir les mauvais usages est aussi important que de permettre des cas d'utilisation.
Les objets Date portent deux casquettes simultanément :
- En tant qu'horodatage : le nombre de millisecondes ou de nanosecondes écoulées depuis un moment précis (appelé l'epoch).
- En tant que combinaison de composants : année, mois, jour, heure, minute, seconde, milliseconde et nanoseconde. Les identificateurs d'année, de mois et de jour n'ont de sens que s'ils sont considérés par rapport à un système de calendrier. L'ensemble de la combinaison correspond à un instant unique de l'histoire lorsqu'il est associé à un fuseau horaire. Les objets
Datefournissent des méthodes pour lire et modifier ces composants.
Les fuseaux horaires sont à l'origine d'un grand nombre de bugs liés aux dates. Lorsqu'on interagit avec un Date par le modèle « combinaison de composants », l'heure ne peut être que dans deux fuseaux : UTC et local (appareil), et il n'est pas possible de définir un fuseau arbitraire. Il manque également le concept de « sans fuseau horaire » : on parle alors de date civile (pour les dates) ou d'heure murale (pour les heures), qui est une heure que l'on « lit sur un calendrier ou une horloge ». Par exemple, si vous réglez une alarme quotidienne, vous voudrez la régler sur « 8:00AM » indépendamment de l'heure d'été ou de vos déplacements vers un autre fuseau horaire.
Un second défaut de Date est l'absence d'un système de calendrier. Beaucoup connaissent peut-être le calendrier grégorien, où il existe deux ères, BC et AD ; il y a 12 mois ; chaque mois compte un nombre de jours différent ; il y a une année bissextile tous les 4 ans ; et ainsi de suite. Cependant, certains de ces concepts peuvent ne pas s'appliquer lorsque vous travaillez avec un autre système de calendrier, comme le calendrier hébraïque, le calendrier chinois, le calendrier japonais, etc. Avec Date, vous ne pouvez travailler qu'avec le modèle du calendrier grégorien.
Il existe d'autres héritages indésirables de Date, tels que le fait que tous les mutateurs modifient l'objet (ce qui provoque souvent des effets secondaires indésirables), le format de chaîne date-heure impossible à analyser de façon cohérente, etc. En fin de compte, la meilleure solution est de construire une nouvelle API depuis le début, ce qui est le rôle de Temporal.
Aperçu de l'API
Temporal est un espace de noms, comme Intl. Il contient plusieurs classes et espaces de noms, chacun étant conçu pour gérer un aspect spécifique de la gestion des dates et des heures. Les classes peuvent être regroupées comme suit :
- Représentation d'une durée temporelle (une différence entre deux points dans le temps) :
Temporal.Duration - Représentation d'un point dans le temps :
- Représentation d'un instant unique dans l'histoire :
- En tant qu'horodatage :
Temporal.Instant - En tant que combinaison de composants date-heure associée à un fuseau horaire :
Temporal.ZonedDateTime
- En tant qu'horodatage :
- Représentation d'une date/heure sans fuseau horaire (toutes préfixées par « Plain ») :
- Date (année, mois, jour) + time (heure, minute, seconde, milliseconde, microseconde, nanoseconde) :
Temporal.PlainDateTime(Note :ZonedDateTimeest équivalent àPlainDateTimeplus un fuseau horaire)- Date (année, mois, jour) :
Temporal.PlainDate- Année, mois :
Temporal.PlainYearMonth - Mois, jour :
Temporal.PlainMonthDay
- Année, mois :
- Heure (heure, minute, seconde, milliseconde, microseconde, nanoseconde) :
Temporal.PlainTime
- Date (année, mois, jour) :
- Date (année, mois, jour) + time (heure, minute, seconde, milliseconde, microseconde, nanoseconde) :
- Représentation d'un instant unique dans l'histoire :
De plus, il existe également un autre espace de noms utilitaire, Temporal.Now, qui fournit des méthodes pour obtenir l'heure actuelle dans différents formats.
Classes d'interface partagée
Il existe de nombreuses classes dans l'espace de noms Temporal, mais elles partagent de nombreuses méthodes similaires. Le tableau suivant répertorie toutes les méthodes de chaque classe (à l'exception des méthodes de conversion) :
Le tableau suivant résume les propriétés disponibles pour chaque classe, vous donnant une idée des informations que chaque classe peut représenter.
Conversion entre les classes
Le tableau ci-dessous résume toutes les méthodes de conversion existant sur chaque classe.
| Comment convertir à partir de... | ||||||||
Instant |
ZonedDateTime |
PlainDateTime |
PlainDate |
PlainTime |
PlainYearMonth |
PlainMonthDay |
||
|---|---|---|---|---|---|---|---|---|
| à... | Instant | / | toInstant() | Convertir d'abord en ZonedDateTime | ||||
ZonedDateTime | toZonedDateTimeISO() | / | toZonedDateTime() | toZonedDateTime() | PlainDate#toZonedDateTime() (pass as argument) | Convertir d'abord en PlainDate | ||
PlainDateTime | Convertir d'abord en ZonedDateTime | toPlainDateTime() | / | toPlainDateTime() | PlainDate#toPlainDateTime() (pass as argument) | |||
PlainDate | toPlainDate() | toPlainDate() | / | Pas de chevauchement d'informations | toPlainDate() | toPlainDate() | ||
PlainTime | toPlainTime() | toPlainTime() | Pas de chevauchement d'informations | / | Pas de chevauchement d'informations | |||
PlainYearMonth | Convertir d'abord en PlainDate | toPlainYearMonth() | Pas de chevauchement d'informations | / | Convertir d'abord en PlainDate | |||
PlainMonthDay | toPlainMonthDay() | Convertir d'abord en PlainDate | / | |||||
Avec ces tableaux, vous devriez avoir une idée de base de la façon de naviguer dans l'API Temporal.
Calendriers
Un calendrier est une façon d'organiser les jours, généralement en périodes de semaines, de mois, d'années et d'ères. La majeure partie du monde utilise le calendrier grégorien, mais il existe de nombreux autres calendriers, notamment dans des contextes religieux et culturels. Par défaut, tous les objets Temporal sensibles au calendrier utilisent le système de calendrier ISO 8601, qui est basé sur le calendrier grégorien et définit des règles supplémentaires de numérotation des semaines. Intl.supportedValuesOf() liste la plupart des calendriers susceptibles d'être pris en charge par les navigateurs. Nous proposons ici un aperçu de la façon dont les systèmes de calendrier sont formés pour vous aider à comprendre les facteurs qui peuvent varier d'un calendrier à l'autre.
Il existe trois grands évènements périodiques sur Terre : sa révolution autour du soleil (365,242 jours pour un tour), la révolution de la lune autour de la Terre (29,53 jours de nouvelle lune à nouvelle lune), et sa rotation sur son axe (24 heures de lever de soleil à lever de soleil). Chaque culture a la même mesure d'un « jour », soit 24 heures. Les changements occasionnels comme l'heure d'été ne font pas partie du calendrier, mais relèvent des informations du fuseau horaire.
- Certains calendriers définissent principalement une année comme ayant en moyenne 365,242 jours, en définissant des années de 365 jours et en ajoutant un jour supplémentaire, le jour intercalaire, environ tous les 4 ans. Ensuite, l'année peut être divisée en parties appelées mois. Ces calendriers sont appelés calendriers solaires. Le calendrier grégorien et le calendrier solaire hijri sont des calendriers solaires.
- Certains calendriers définissent principalement un mois comme ayant en moyenne 29,5 jours, en alternant des mois de 29 et 30 jours. Ensuite, 12 mois peuvent former une année de 354 jours. Ces calendriers sont appelés calendriers lunaires. Le calendrier islamique est un calendrier lunaire. Comme une année lunaire est artificielle et ne correspond pas au cycle des saisons, les calendriers lunaires sont généralement plus rares.
- Certains calendriers définissent aussi principalement les mois selon les cycles lunaires, comme les calendriers lunaires. Ensuite, pour compenser l'écart de 11 jours avec l'année solaire, un mois supplémentaire, le mois intercalaire, est ajouté environ tous les 3 ans. Ces calendriers sont appelés calendriers lunisolaire. Le calendrier hébraïque et le calendrier chinois sont des calendriers lunisolaire.
Dans Temporal, chaque date selon un système de calendrier est identifiée de façon unique par trois composants : year, month et day. Si year est généralement un entier positif, il peut aussi être nul ou négatif, et il augmente de façon monotone avec le temps. L'année 1 (ou 0, si elle existe) est appelée l'époque du calendrier, et elle est arbitraire pour chaque calendrier. month est un entier positif qui s'incrémente de 1 à chaque fois, en commençant à 1 et en finissant à date.monthsInYear, puis revient à 1 à mesure que l'année avance. day est aussi un entier positif, mais il peut ne pas commencer à 1 ou s'incrémenter de 1 à chaque fois, car des changements politiques peuvent entraîner des jours sautés ou répétés. Mais en général, day augmente de façon monotone et revient à 1 à mesure que le mois avance.
En plus de year, une année peut aussi être identifiée de façon unique par la combinaison de era et eraYear, pour les calendriers qui utilisent des ères. Par exemple, le calendrier grégorien utilise les ères « CE » (ère commune) et « BCE » (avant l'ère commune), et l'année -1 est la même que { era: "bce", eraYear: 2 } (notez que l'année 0 existe toujours pour tous les calendriers ; pour le calendrier grégorien, elle correspond à 1 BCE selon la numérotation astronomique des années (angl.)). era est une chaîne en minuscules, et eraYear est un entier arbitraire qui peut être nul ou négatif, ou même décroître avec le temps (généralement pour l'ère la plus ancienne).
Note :
Toujours utiliser era et eraYear ensemble ; n'utilisez pas une propriété sans l'autre. De plus, pour éviter les conflits, n'associez pas year et era/eraYear pour désigner une année. Choisissez une représentation d'année et utilisez-la de façon cohérente.
Faites attention aux hypothèses incorrectes suivantes concernant les années :
- Ne supposez pas que
eraeteraYearsont toujours présents ; ils peuvent êtreundefined. - Ne supposez pas que
eraest une chaîne conviviale ; utiliseztoLocaleString()pour formater votre date. - Ne supposez pas que deux valeurs
yearde calendriers différents sont comparables ; utilisez plutôt la méthode statiquecompare(). - Ne supposez pas que les années ont 365/366 jours et 12 mois ; utilisez
daysInYearetmonthsInYear. - Ne supposez pas que les années bissextiles (
inLeapYearvauttrue) ont un jour supplémentaire ; elles peuvent avoir un mois supplémentaire.
En plus de month, un mois dans une année peut aussi être identifié de façon unique par le monthCode. monthCode correspond généralement au nom du mois, mais pas month. Par exemple, dans le cas des calendriers lunisolaire, deux mois ayant le même monthCode, dont l'un appartient à une année bissextile et l'autre non, auront des valeurs month différentes s'ils viennent après le mois intercalaire, en raison de l'insertion d'un mois supplémentaire.
Note :
Pour éviter les conflits, n'associez pas month et monthCode pour désigner un mois. Choisissez une représentation de mois et utilisez-la de façon cohérente. month est plus utile si vous avez besoin de l'ordre des mois dans une année (par exemple, lors d'une boucle sur les mois), tandis que monthCode est plus utile si vous avez besoin du nom du mois (par exemple, pour stocker des anniversaires).
Faites attention aux hypothèses incorrectes suivantes concernant les mois :
- Ne supposez pas que
monthCodeetmonthcorrespondent toujours. - Ne supposez pas le nombre de jours dans un mois ; utilisez
daysInMonth. - Ne supposez pas que
monthCodeest une chaîne conviviale ; utiliseztoLocaleString()pour formater votre date. - En général, n'enregistrez pas le nom des mois dans un tableau ou un objet. Même si
monthCodecorrespond généralement au nom du mois dans un calendrier, il est recommandé de toujours calculer le nom du mois, par exemple avecdate.toLocaleString("fr-FR", { calendar: date.calendarId, month: "long" }).
En plus de day (qui est un index basé sur le mois), un jour dans une année peut aussi être identifié de façon unique par le dayOfYear. dayOfYear est un entier positif qui s'incrémente de 1 à chaque fois, en commençant à 1 et en finissant à date.daysInYear.
Le concept de « semaine » n'est lié à aucun évènement astronomique, mais est une construction culturelle. Bien que la longueur la plus courante soit de 7 jours, les semaines peuvent aussi avoir 4, 5, 6, 8 jours ou plus — ou même ne pas avoir de nombre fixe de jours. Pour obtenir le nombre exact de jours de la semaine d'une date, utilisez la propriété daysInWeek de la date. Temporal identifie les semaines par la combinaison de weekOfYear et yearOfWeek. weekOfYear est un entier positif qui s'incrémente de 1 à chaque fois, en commençant à 1, puis revient à 1 à mesure que l'année avance. yearOfWeek est généralement identique à year, mais peut différer au début ou à la fin de chaque année, car une semaine peut chevaucher deux années, et yearOfWeek choisit l'une des deux années selon les règles du calendrier.
Note :
Toujours utiliser weekOfYear et yearOfWeek ensemble ; n'utilisez pas weekOfYear et year.
Faites attention aux hypothèses incorrectes suivantes concernant les semaines :
- Ne supposez pas que
weekOfYearetyearOfWeeksont toujours présents ; ils peuvent êtreundefined. - Ne supposez pas que les semaines font toujours 7 jours ; utilisez
daysInWeek. - Notez que l'API
Temporalactuelle ne prend pas en charge les dates année-semaine, vous ne pouvez donc pas construire de dates avec ces propriétés ni les sérialiser dans ce format. Ce sont uniquement des propriétés informatives.
Format RFC 9557
Toutes les classes Temporal peuvent être sérialisées et désérialisées en utilisant le format défini dans la RFC 9557 (angl.), qui est basé sur ISO 8601 / RFC 3339 (angl.). Le format, dans sa forme complète, est le suivant (les espaces ne sont là que pour la lisibilité et ne doivent pas être présents dans la chaîne de caractères réelle) :
YYYY-MM-DD T HH:mm:ss.sssssssss Z/±HH:mm [time_zone_id] [u-ca=calendar_id]
Chaque classe a des exigences différentes concernant la présence de chaque composant, vous trouverez donc une section intitulée « Format RFC 9557 » dans la documentation de chaque classe, qui précise le format reconnu par cette classe.
Ceci est très similaire au format de chaîne date-heure utilisé par Date, qui est aussi basé sur ISO 8601. La principale nouveauté est la possibilité de définir des composants de microsecondes et nanosecondes, ainsi que la possibilité de définir le fuseau horaire et le système de calendrier.
Dates représentables
Tous les objets Temporal qui représentent une date de calendrier spécifique imposent une limite similaire à l'étendue des dates représentables, qui est de ±108 jours (inclus) à partir de l'époque Unix, ou la plage d'instants de -271821-04-20T00:00:00 à +275760-09-13T00:00:00. Il s'agit de la même plage que pour les dates valides. Plus précisément :
Temporal.InstantetTemporal.ZonedDateTimeappliquent cette limite directement sur leur valeurepochNanoseconds.Temporal.PlainDateTimeinterprète la date-heure dans le fuseau horaire UTC et exige qu'elle soit dans la plage ±(108 + 1) jours (exclus) à partir de l'époque Unix, donc sa plage valide est de-271821-04-19T00:00:00à+275760-09-14T00:00:00, exclus. Cela permet de convertir n'importe quelZonedDateTimeenPlainDateTimequel que soit son décalage.Temporal.PlainDateapplique la même vérification quePlainDateTimeau midi (12:00:00) de cette date, donc sa plage valide est de-271821-04-19à+275760-09-13. Cela permet de convertir n'importe quelPlainDateTimeenPlainDatequelle que soit son heure, et inversement.Temporal.PlainYearMontha la plage valide de-271821-04à+275760-09. Cela permet de convertir n'importe quelPlainDateenPlainYearMonthquelle que soit sa date (sauf si le premier jour d'un mois non ISO tombe dans le mois ISO-271821-03).
Les objets Temporal refuseront de construire une instance représentant une date/heure au-delà de cette limite. Cela inclut :
- L'utilisation du constructeur ou de la méthode statique
from(). - L'utilisation de la méthode
with()pour mettre à jour les champs du calendrier. - L'utilisation de
add(),subtract(),round(), ou toute autre méthode pour dériver de nouvelles instances.
Propriétés statiques
Temporal.Duration-
Représente une différence entre deux points dans le temps, qui peut être utilisée dans l'arithmétique de date/heure. Elle est fondamentalement représentée comme une combinaison de valeurs d'années, mois, semaines, jours, heures, minutes, secondes, millisecondes, microsecondes et nanosecondes.
Temporal.Instant-
Représente un point unique dans le temps, avec une précision à la nanoseconde. Elle est fondamentalement représentée comme le nombre de nanosecondes écoulées depuis l'époque Unix (minuit au début du 1er janvier 1970, UTC), sans aucun fuseau horaire ni système de calendrier.
Temporal.Now-
Fournit des méthodes pour obtenir l'heure actuelle dans différents formats.
Temporal.PlainDate-
Représente une date de calendrier (une date sans heure ni fuseau horaire) ; par exemple, un évènement sur un calendrier qui a lieu toute la journée, quel que soit le fuseau horaire. Elle est fondamentalement représentée comme une date de calendrier ISO 8601, avec les champs année, mois et jour, et un système de calendrier associé.
Temporal.PlainDateTime-
Représente une date (date de calendrier) et une heure (heure murale) sans fuseau horaire. Elle est fondamentalement représentée comme une combinaison d'une date (avec un système de calendrier associé) et d'une heure.
Temporal.PlainMonthDay-
Représente le mois et le jour d'une date de calendrier, sans année ni fuseau horaire ; par exemple, un évènement sur un calendrier qui revient chaque année et a lieu toute la journée. Elle est fondamentalement représentée comme une date de calendrier ISO 8601, avec les champs année, mois et jour, et un système de calendrier associé. L'année est utilisée pour lever l'ambiguïté du mois-jour dans les systèmes de calendrier non ISO.
Temporal.PlainTime-
Représente une heure sans date ni fuseau horaire ; par exemple, un évènement récurrent qui a lieu à la même heure chaque jour. Elle est fondamentalement représentée comme une combinaison de valeurs d'heure, minute, seconde, milliseconde, microseconde et nanoseconde.
Temporal.PlainYearMonth-
Représente l'année et le mois d'une date de calendrier, sans jour ni fuseau horaire ; par exemple, un évènement sur un calendrier qui a lieu tout le mois. Elle est fondamentalement représentée comme une date de calendrier ISO 8601, avec les champs année, mois et jour, et un système de calendrier associé. Le jour est utilisé pour lever l'ambiguïté de l'année-mois dans les systèmes de calendrier non ISO.
Temporal.ZonedDateTime-
Représente une date et une heure avec un fuseau horaire. Elle est fondamentalement représentée comme une combinaison d'un instant, d'un fuseau horaire et d'un système de calendrier.
Temporal[Symbol.toStringTag]-
La valeur initiale de la propriété
[Symbol.toStringTag]est la chaîne de caractères"Temporal". Cette propriété est utilisée dansObject.prototype.toString().
Spécifications
| Specification |
|---|
| Temporal> # sec-temporal-objects> |