Date disparaît, Temporal arrive
(piccalil.li)- L’objet Date existant de JavaScript est critiqué pour son caractère incomplet et incohérent, et l’API Temporal est présentée comme son remplaçant
- Date fonctionne comme un objet mutable, en décalage avec le concept réel de date, et souffre de problèmes structurels comme des erreurs de parsing et des limites dans la gestion des fuseaux horaires
- Temporal fournit un nouveau modèle de gestion des dates et heures fondé sur l’immuabilité, avec des classes détaillées comme
PlainDate,ZonedDateTime,Duration - Les méthodes de Temporal ne modifient pas l’objet existant mais renvoient un nouvel objet, permettant un chaînage d’opérations clair et sûr
- Temporal est actuellement au stade 3 de standardisation (Stage 3) et bénéficie d’une prise en charge expérimentale dans les navigateurs récents comme Chrome et Firefox
Problèmes de l’objet Date de JavaScript
- Le constructeur
Dateprovoque de la confusion avec des règles de parsing incohérentes et une indexation peu intuitive- Exemple : le mois (
month) commence à 0, tandis que le jour (day) et l’année (year) commencent à 1 - Les chaînes
"99"et"100"sont interprétées respectivement comme 1999 et 0100, ce qui illustre le manque de cohérence
- Exemple : le mois (
Datea été conçu autour du temps et stocke en interne un timestamp Unix (en millisecondes)- La prise en charge des fuseaux horaires est limitée, et l’objet ne comprend ni l’heure d’été (DST) ni les calendriers non grégoriens
- En raison de ces limites, il est courant de dépendre de grandes bibliothèques tierces comme Moment.js ou date-fns, ce qui entraîne une baisse des performances
Conflit entre immuabilité et notion de référence
- En JavaScript, les valeurs primitives sont immuables et stockées par valeur, tandis que les objets sont stockés par référence et peuvent être modifiés
Dateest un objet créé via un constructeur, il est donc mutable- Exemple : quand on appelle
setMonth()ousetDate(), l’objet d’origine est directement modifié
- Exemple : quand on appelle
- Cela entraîne des changements de valeur inattendus entre des variables qui référencent le même objet
- Exemple : si une fonction reçoit
todayen argument et modifie la date en interne, l’objettodayd’origine est lui aussi modifié
- Exemple : si une fonction reçoit
Temporal : une nouvelle API de date et d’heure
Temporaln’est pas un constructeur mais un objet d’espace de noms, de structure similaire àMath- Principaux composants :
PlainDate,PlainDateTime,PlainTime,ZonedDateTime,Duration,Now, etc.
- Principaux composants :
Temporal.Nowrenvoie le moment présent sous différentes formesplainDateISO()→ date au format ISOzonedDateTimeISO()→ date et heure avec fuseau horaire
- Les objets Temporal fournissent un ensemble de méthodes explicites
add({ days: 1 }),subtract({ years: 2 }), etc. permettent d’effectuer des opérations explicites par unité- Au lieu de modifier l’objet existant, ils renvoient un nouvel objet, préservant ainsi l’immuabilité
Fonctionnement et avantages de Temporal
- Les objets Temporal restent des objets, mais suivent un schéma d’utilisation intentionnellement immuable
- Exemple :
today.add({ days: 1 })renvoie un nouvel objet date, tandis quetodayreste inchangé
- Exemple :
- Temporal offre une syntaxe plus concise et plus claire que
Date- Exemple :
const today = Temporal.Now.plainDateISO(); console.log(`Tomorrow will be ${ today.add({ days: 1 }) }. Today is ${ today }.`); // 결과: Tomorrow will be 2026-01-01. Today is 2025-12-31.
- Exemple :
- Il répond aux besoins modernes comme la définition des fuseaux horaires, le calcul de durées et le maintien du format ISO
- Grâce au chaînage de méthodes comme
add,subtract,sinceetuntil, il devient possible d’exprimer simplement des calculs de date complexes
État de la standardisation et perspectives
Temporala atteint le stade 3 (Stage 3) de la proposition ECMAScript, un niveau où l’implémentation par les navigateurs est recommandée- Une prise en charge expérimentale a déjà commencé dans Chrome et Firefox, et d’autres navigateurs devraient suivre
- Les développeurs peuvent dès maintenant participer à l’amélioration de la spécification en testant l’API et en faisant des retours
Datecontinuera d’exister, mais à l’avenir, Temporal devrait devenir la méthode par défaut pour gérer les dates- L’article se conclut en disant qu’« il aurait fallu le remplacer en 1995, mais même maintenant, Temporal.Now arrive au moment idéal »
1 commentaires
Réactions sur Hacker News
Cet article traite des nombreux comportements aberrants du constructeur Date de JavaScript
En particulier, il explique le problème où le format
'YYYY-MM-DD'est interprété comme minuit UTC, ce qui décale la date d’un jour dans les fuseaux horaires locauxÀ l’origine, dans l’ISO 8601, si aucun fuseau horaire n’est précisé, cela devrait être interprété comme l’heure locale, mais lors de la rédaction de la spec ES5, une erreur a conduit à le traiter comme
"Z"(UTC)Une correction a ensuite été envisagée dans ES2015, mais comme d’innombrables sites web dépendaient déjà de ce comportement erroné, elle a été annulée pour des raisons de compatibilité web
Voir la section Broken Parser pour plus de détails
'strict datetime', à l’image de'use strict'Cela aurait permis d’appliquer sélectivement un comportement correct sans introduire d’incompatibilités avec le code existant
Ou bien un mécanisme du type
import Date from 'browser:date', permettant de charger via un module interne un objet global corrigéPour quelque chose comme un anniversaire, qui ne représente qu’une date, il est absurde que le fuseau horaire la modifie
Je me souviens qu’Outlook stockait les anniversaires avec un fuseau horaire, ce qui les faisait glisser d’un jour à chaque changement de pays
Mais y avait-il vraiment une alternative ? Forcer des branches selon la version du navigateur, comme à l’époque d’IE5, aurait sans doute été pire
J’envie vraiment la gestion du temps dans Rails et Ruby
Une API comme
Time.current.in_time_zone('America/Los_Angeles') + 3.days - 4.months + 1.hourest intuitive et puissanteRuby surcharge les objets Time en un seul objet cohérent, ce qui évite presque totalement les soucis de conversion ou de casting
En JS aussi, ce serait formidable de pouvoir écrire simplement quelque chose comme
new Date().add({ days: 1 })3.days - 4.months + 1.hourEt il reste permis de débattre de l’intérêt de surcharger la bibliothèque standard de cette manière
C’est dommage que Safari ne prenne toujours pas en charge l’API Temporal
Espérons que ce sera le cas l’année prochaine
Date a beaucoup de problèmes en JavaScript, mais je ne pense pas que le fait que ce soit un objet soit en soi le vrai souci
Il aurait mieux valu qu’il soit immuable, mais qu’un objet mutable soit modifié n’a rien de surprenant
Le véritable danger de la mutabilité vient des modifications non locales, pas des modifications locales
Il est gênant que l’API Temporal ne gère absolument pas les informations de seconde intercalaire (leap second)
J’aimerais créer un outil JS pour des calculs astronomiques, et il faut des données de secondes intercalaires pour les conversions UTC
Il existe des contournements comme
temporal-tai, mais cela oblige à maintenir côté client un fichier de secondes intercalaires, ce qui est pénibleÀ cause de la SOP (politique CORS), on ne peut pas non plus récupérer directement ce fichier depuis un site externe
Les navigateurs se mettent pourtant à jour régulièrement, alors pourquoi n’intègrent-ils pas ces informations ?
Si le serveur définit l’en-tête
Access-Control-Allow-Originou les fournit sous forme de fichier JS, c’est possibleEn revanche, inclure et maintenir nativement ces données dans le navigateur peut représenter un coût important
L’UTC inclut par définition les secondes intercalaires, donc en réalité, il serait plus juste de dire qu’elle ne gère que le temps POSIX
Dans l’exemple de code, il faudrait dire qu’on bascule vers les années 1900 à partir de
"50", et non"33"— simple signalement de coquilleJ’utilise le polyfill Temporal et jusqu’ici j’en suis très satisfait
C’est acceptable côté serveur ou dans de grosses applications, mais cela peut peser pour les petites apps
Il est étrange que l’article ne mentionne jamais
Date.now()Pour comparer avec Temporal, il aurait fallu partir de
Date.now()comme référenceCette fonction renvoie le nombre de millisecondes écoulées depuis le 1er janvier 1970
Temporal offre certes une API plus agréable, mais au fond, le but reste d’exprimer une distance relative dans le temps
Dans ce cas, comment convertir directement vers le format voulu sans passer par Date ?
Petite correction, mais importante : on dit non pas “daylight savings time”, mais “daylight saving time”
Je n’avais jamais réalisé à quel point JS Date était bancal
Avec un peu plus de prudence à l’époque, d’innombrables développeurs auraient pu éviter tous ces pièges