Introduction : pourquoi le temps est un casse-tête pour chaque développeur
\n\nAvez-vous déjà attrapé un bug où un utilisateur de Vladivostok voit la date du lendemain alors que le calendrier indique aujourd'hui ? Ou lorsque le serveur AWS us-east-1 envoie une heure que votre client à Kaliningrad interprète comme 3 heures du matin ? Bienvenue dans le monde des fuseaux horaires en TypeScript.
\n\nLe problème est que JavaScript (et TypeScript comme surcouche) a été conçu à l'origine pour les navigateurs. L'objet natif Date n'est, en substance, qu'un horodatage UTC déguisé. Il ne sait pas gérer les fuseaux horaires comme nous en avons besoin. Et si vous écrivez une application sérieuse en TypeScript — que ce soit une interface d'administration en React, un backend en Node.js ou une application mobile en React Native — vous ne pouvez pas vous passer d'une gestion correcte des timezones.
Dans cet article, je vais vous montrer comment apprivoiser le temps. Nous aborderons les concepts de base, apprendrons à utiliser les bibliothèques modernes et éviterons les pièges typiques. C'est parti !
\n\nCe qu'il faut savoir sur les fuseaux horaires avant d'écrire du code
\n\nAvant de plonger dans TypeScript, mettons les points sur les i. Il existe deux types de temps dans le monde : le temps absolu (UTC) et le temps local (celui que voit l'utilisateur).
\n\n- \n
- UTC (Temps Universel Coordonné) — c'est la référence. Les serveurs, bases de données et API doivent stocker le temps en UTC. C'est une règle en fer. \n
- Base de données IANA des fuseaux horaires — c'est le dictionnaire des fuseaux horaires comme
Europe/Moscow,Asia/Vladivostok. Ce sont ces chaînes, et non des abréviations comme MSK ou PST, qu'il faut utiliser dans le code. \n - Offset (décalage) — c'est la différence avec UTC, par exemple +03:00. Mais rappelez-vous : le décalage peut changer à cause de l'heure d'été (DST). Donc stocker un offset au lieu d'une zone IANA est une mauvaise idée. \n
\n\n\nRègle d'or : stocker en UTC, convertir côté client, utiliser les chaînes IANA pour identifier les zones.
\n
Pourquoi le Date natif ne suffit pas : douleur et souffrance
\n\nRegardons la vérité en face : new Date() en TypeScript, c'est comme un couteau suisse dont la lame est cassée. Il ne sait que stocker un horodatage et l'afficher dans le fuseau local du navigateur ou du serveur. Essayez de faire quelque chose de plus complexe :
// Mauvais exemple : essayer de travailler avec les fuseaux avec les moyens natifs\nconst date = new Date('2024-03-10T12:00:00');\nconsole.log(date.toLocaleString('ru-RU', { timeZone: 'Europe/Moscow' }));\n// Affiche : "10.03.2024, 15:00:00" — mais c'est juste une chaîne, pas un objet !\n\n// Et si on a besoin d'un Date dans un autre fuseau ?\n// Oups... le JS natif ne sait pas créer un Date lié à un fuseau.\n\n\nLe problème est que Date stocke toujours le temps en UTC. Toutes les méthodes comme getHours() ne font que convertir l'UTC en heure locale du navigateur. Vous ne pouvez pas obtenir un objet Date qui "pense" qu'il est à New York.
C'est pourquoi nous utilisons des bibliothèques. Dans l'écosystème TypeScript, il y a deux candidats principaux : Luxon et date-fns-tz.
\n\nLuxon : l'artillerie lourde pour travailler avec les dates
\n\nLuxon est une bibliothèque moderne créée par l'auteur de Moment.js (qui est désormais déprécié). Elle a été écrite de zéro, utilise le natif Intl.DateTimeFormat et est parfaitement typée pour TypeScript.
Installation de Luxon
\n\nnpm install luxon\nnpm install --save-dev @types/luxon\n\n\nCréation d'une date dans un fuseau horaire spécifique
\n\nimport { DateTime } from 'luxon';\n\n// Créons une date dans le fuseau Europe/Moscow\nconst moscowTime = DateTime.fromObject(\n { year: 2024, month: 3, day: 10, hour: 12 },\n { zone: 'Europe/Moscow' }\n);\nconsole.log(moscowTime.toISO());\n// Sortie : "2024-03-10T12:00:00.000+03:00"\n\n// Conversion vers un autre fuseau\nconst nyTime = moscowTime.setZone('America/New_York');\nconsole.log(nyTime.toISO());\n// Sortie : "2024-03-10T05:00:00.00