Horloge des fuseaux
Bruxelles, Genève, Montréal, Tokyo à l'heure exacte, heure d'été comprise, avec un curseur pour planifier un appel. Le bon exercice pour laisser l'API Intl gérer les fuseaux horaires.
- Afficher une heure dans un fuseau avec Intl.DateTimeFormat
- Calculer l'écart entre deux villes à un instant donné
- Repérer un changement de jour
Pourquoi une horloge des fuseaux ? Un client à Montréal, une amie à Tokyo, une réunion à Genève : quelle heure est-il là-bas, et est-ce qu'on peut appeler ? Les fuseaux horaires sont pleins de pièges : heure d'été à des dates différentes, décalages d'une demi-heure, changement de jour.
On ne calcule rien à la main. Le navigateur connaît la base officielle des fuseaux, et Intl.DateTimeFormat affiche n'importe quel instant dans n'importe quelle ville avec l'option timeZone.
Le curseur décale l'instant : glissez de trois heures pour voir si l'appel tombe en pleine nuit quelque part.
Pourquoi en JavaScript simple ? Une seule API, aucune bibliothèque, et la règle d'or : on manipule des instants, on n'affiche les fuseaux qu'à la fin.
LES VILLES
Des identifiants officiels, pas des décalages fixes comme +1 ou +9.
const VILLES = [['Bruxelles', 'Europe/Brussels'], ['Genève', 'Europe/Zurich'], ['Montréal', 'America/Toronto'], ['Tokyo', 'Asia/Tokyo']];AFFICHER UNE HEURE DANS UN FUSEAU
Un seul instant, plusieurs façons de l'afficher.
function heure(instant, fuseau) { return new Intl.DateTimeFormat('fr-BE', { timeZone: fuseau, hour: '2-digit', minute: '2-digit', weekday: 'short', hourCycle: 'h23', }).format(instant); }L'ÉCART AVEC UTC
On relit les morceaux de la date dans le fuseau, et on compare à l'instant réel.
function ecart(fuseau, instant) { const p = {}; new Intl.DateTimeFormat('en-US', { timeZone: fuseau, hourCycle: 'h23', year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' }) .formatToParts(instant).forEach(x => (p[x.type] = x.value)); const local = Date.UTC(p.year, p.month - 1, p.day, p.hour, p.minute); return Math.round((local - instant.getTime()) / 60000); // en minutes }LA DIFFÉRENCE ENTRE DEUX VILLES
Calculée à l'instant affiché : pendant trois semaines par an, Bruxelles et Montréal n'ont pas leur écart habituel.
const diff = (a, b, instant) => (ecart(b, instant) - ecart(a, instant)) / 60;
PLANIFIER
Le curseur décale l'instant, pas les fuseaux.
const decalage = Number(curseur.value); // en heures const instant = new Date(Date.now() + decalage * 3600000); for (const [nom, fuseau] of VILLES) console.log(nom, heure(instant, fuseau));
PIÈGE 1 : Des décalages écrits en dur
Mauvais : Tokyo = Bruxelles + 8. C'est faux la moitié de l'année, car Tokyo n'a pas d'heure d'été.
Correct : des identifiants comme Asia/Tokyo, et laisser Intl appliquer les règles du moment.
PIÈGE 2 : Modifier la date pour changer de fuseau
Mauvais : ajouter des heures à un objet Date pour « le mettre à l'heure de Tokyo ». On fabrique un faux instant, et les calculs suivants se trompent.
Correct : garder un seul instant réel, et ne choisir le fuseau qu'au moment de l'afficher.
PIÈGE 3 : Oublier le changement de jour
Mauvais : n'afficher que l'heure. 08:41 à Tokyo, c'est déjà demain pour Bruxelles.
Correct : afficher le jour à côté de l'heure, et signaler la nuit pour éviter un appel à 3 h.
- Des horaires de bureau par ville, et une bande verte quand tout le monde est disponible.
- Une recherche parmi tous les fuseaux avec Intl.supportedValuesOf('timeZone').
- Des horloges à aiguilles en SVG, une par ville.
- Créez chaque Intl.DateTimeFormat une seule fois et gardez-le en cache : c'est l'appel le plus coûteux.
- Rafraîchissez au changement de minute plutôt qu'à chaque seconde.
La liste des villes et le décalage vivent dans deux useState.
Un useEffect met à jour un état « maintenant » toutes les quinze secondes, et le nettoie au démontage.
Avec un rendu serveur, l'heure du serveur et celle du navigateur diffèrent : affichez l'horloge seulement côté client.
Chargement des commentaires…