Le parseur de dates JavaScript dangereux : comment éviter les pièges
Le constructeur new Date(string) en JavaScript tente d'extraire une date à partir de n'importe quelle chaîne, souvent avec des résultats inattendus. Ce n'est pas une erreur — c'est une fonctionnalité des moteurs V8 et SpiderMonkey, où le parseur interprète agressivement le texte.
Des exemples illustrent bien le problème :
new Date("2020-01-23")
// Wed Jan 22 2020 19:00:00 GMT-0500 (interprété comme UTC)
new Date("Today is 2020-01-23")
// Thu Jan 23 2020 00:00:00 GMT-0500 (heure locale)
new Date("Route 66")
// Sat Jan 01 1966 00:00:00 GMT-0500
new Date("Beverly Hills, 90210")
// Mon Jan 01 90210 00:00:00 GMT-0500
Ces conversions produisent des objets Date valides mais aux valeurs erronées — ce qui rend le débogage compliqué. Le cas « Catch 22 » retourne Invalid Date, rare mais en réalité correct.
Comment fonctionne le parseur V8
La spécification ECMAScript impose un parsing uniquement pour une sous-ensemble de l'ISO 8601. Tout le reste dépend de l'implémentation.
Algorithme de V8 :
- Vérifier si la chaîne suit l'ISO 8601 : doit commencer par une année à quatre chiffres ou un signe.
- Recourir au parseur hérité : ignorer les mots jusqu'à trouver le premier nombre.
- Traiter les nombres dans
DayComposer:
- 1–12 : interprétés comme mois.
- 13–31 : ambigus, souvent rejetés.
- 32+ : traités comme année (50–99 +1900).
- Valeur par défaut : 1er janvier.
Cela explique pourquoi "Route 66" devient 1966 et "90210" devient l'année 90210.
Confusion liée aux fuseaux horaires
Les chaînes ISO comme "2020-01-23" sont analysées en UTC, tandis que les formats anciens utilisent l'heure locale. La différence provient des préfixes :
- Chaîne pure ISO : analysée en UTC.
- Chaînes contenant du texte : mode hérité, heure locale.
Les espaces avant ou après changent le comportement du parseur, pouvant décaler les résultats d'un jour selon le fuseau horaire.
Safari (JavaScriptCore) est plus strict : il rejette les exemples hérités et les chaînes avec espaces en fin.
Bugs réels et solutions
Dans des projets concrets, revenir à new Date() pour l’entrée utilisateur peut transformer "Route 66" en date, corrompant les tables de données. Solution : se fier uniquement à des parseurs personnalisés avec validation regex.
Bonnes pratiques pour développeurs confirmés :
- Valider le format avec regex avant d’appeler
new Date(). - Utiliser
date-fns parseISO()pour un parsing stricte de l’ISO. - Pour un contrôle total, utiliser des bibliothèques comme Luxon ou Day.js avec parseurs sur mesure.
- Jamais utiliser
new Date(string)avec une entrée non fiable. - Tester sur plusieurs navigateurs : V8, SpiderMonkey, JSC.
JavaScript vs Python : une comparaison
Python évite toute ambiguïté :
datetime.fromisoformat(): accepte uniquement l’ISO 8601.strptime(): format strict, aucun caractère superflu autorisé.
Le parseur JavaScript hérité devine silencieusement ; Python lance une ValueError.
Points clés
- Le parseur
Datecrée des objets valides mais incorrects à partir de textes aléatoires. - Le comportement du parseur (ISO vs hérité) dépend des préfixes et des espaces.
- En production : valider toujours l’entrée avant le parsing.
- Migration vers l’API Temporal pour un code pérenne.
- Le test multi-navigateur est essentiel en raison des différences entre moteurs.
— Editorial Team
Aucun commentaire pour le moment.