Methodology
Méthodologie date et heure
Où les mathématiques de dates naïves échouent — et comment chaque outil /datetime/ les contourne.
By Buğra SözeriPublished
L’arithmétique de date et heure est l’une des catégories de code les plus tentées et les plus boguées dans tout grand codebase. Les quatre outils sous notre cluster Date & heure s’attaquent chacun à un sous-problème différent ; cette page explique les mathématiques derrière chacun.
Calculateur d’âge — emprunt calendaire
L’âge en années-mois-jours n’est pas juste “aujourd’hui moins l’anniversaire divisé par 365,25” — cette approximation accumule un jour d’erreur tous les 4 à 7 ans. L’algorithme correct utilise l’emprunt calendaire :
- Calculer la différence d’années :
maintenant.année − naissance.année. - Calculer la différence de mois. Si
maintenant.mois < naissance.mois, emprunter 12 mois au comptage des années. - Calculer la différence de jours. Si
maintenant.jour < naissance.jour, emprunter des jours au comptage des mois en utilisant la longueur réelle du mois calendaire précédent.
L’étape 3 est là où le code naïf échoue. “Longueur du mois précédent” n’est pas 30 ou 31 — cela dépend du mois précédent (février fait 28 ou 29 jours, les autres 30 ou 31). Notre calculateur d’âge utilise new Date(année, mois, 0) (qui retourne le dernier jour du mois précédent) pour obtenir le bon nombre à chaque fois, y compris pour les années bissextiles.
Exemple concret
Naissance : 1990-12-31. Aujourd’hui : 2026-05-14. Différence d’années : 36. Différence de mois : −7 (mai moins décembre). Emprunter une année, la différence de mois devient 5. Différence de jours : 14 − 31 = −17. Emprunter un mois ; le mois précédent est avril, qui a 30 jours, donc ajouter 30, donnant une différence de jours de 13. Résultat : 35 ans, 4 mois, 13 jours.
Différence de dates — trois unités, un dénominateur
L’outil de différence de dates rapporte l’écart entre deux dates en jours, semaines et heures simultanément. Les mathématiques sont simples :
jours = (b.getTime() − a.getTime()) / 86 400 000semaines = jours / 7 · heures = jours × 24
La subtilité est la gestion du fuseau horaire. Les deux dates sont normalisées à minuit UTC avant la soustraction, donc les transitions DST n’introduisent pas de jours fractionnaires. Une différence de dates couvrant un passage à l’heure d’été est toujours un nombre entier de jours, comme les utilisateurs s’y attendent.
Jours ouvrables — du lundi au vendredi entre deux dates
Le compteur de jours ouvrables utilise l’algorithme le plus simple possible : parcourir chaque jour calendaire entre les deux dates et incrémenter un compteur quand le jour de la semaine est du lundi au vendredi.
À ~250 jours de semaine par an et une construction d’objet Date prenant en moyenne ~1 µs dans V8 moderne, cela se termine en microsecondes pour toute plage de dates inférieure à un siècle. Nous n’utilisons pas de formule en forme fermée car elle n’est que marginalement plus rapide et nettement plus difficile à lire.
Ce qui n’est pas inclus : les jours fériés nationaux. L’observance des jours fériés varie selon le pays, l’année (la plupart sont à date fixe mais un sous-ensemble significatif suit le calendrier lunaire ou est défini comme “nième jour de semaine du mois”) et le secteur. Nous aurions besoin de nous appuyer sur un jeu de données organisé pour le faire correctement ; l’outil de jours ouvrables reste uniquement par jours de semaine intentionnellement.
Convertisseur de fuseaux horaires — IANA tzdata + Intl.DateTimeFormat
Les fuseaux horaires sont des constructions politiques, pas géographiques, et leurs règles changent. Les dates de début de l’heure d’été, les expériences DST toute l’année, les divisions et fusions à mesure que les pays se réorganisent — tout cela est capturé dans le bundle IANA tzdata livré avec chaque système d’exploitation moderne.
Notre convertisseur de fuseaux horaires accède à ces données via le Intl.DateTimeFormatintégré du navigateur. Nous n’intégrons jamais notre propre tzdata. Cela compte parce que :
- tzdata se met à jour plusieurs fois par an à mesure que les pays changent de règles.
- Intégrer notre propre copie figerait ces données au moment du build.
- Le tzdata au niveau OS est mis à jour par le fournisseur OS selon un calendrier de sécurité plus rapide que le nôtre.
L’algorithme de conversion d’heure locale
Étant donné “14h00 le 2026-07-04 à Europe/Istanbul, quelle heure est-il à America/Los_Angeles ?” :
- Traiter “14h00 le 2026-07-04” comme un horodatage UTC (appeler cela
estimation). - Demander à Intl.DateTimeFormat : à
estimation, quel décalage a Europe/Istanbul ? (UTC+3.) - Ajuster : l’instant UTC réel est
estimation − 3 heures. - Rendre cet instant UTC sur l’horloge murale de Los_Angeles.
Cela gère les zones à demi-heure (Inde, UTC+5:30) et à 45 minutes (Népal, UTC+5:45) sans cas particuliers. Le seul cas qui pose problème est l’écart du “passage à l’heure d’été” — 2h30 n’existe pas dans une zone qui saute de 2h00 à 3h00 — mais le calculateur retourne le résultat avec une heure de décalage plutôt qu’échouer, ce qui reste une information utile.
La valeur par défaut ISO 8601
Toutes les entrées de dates dans l’interface utilisent le format ISO 8601 (YYYY-MM-DD). Tous les objets Dateproduits en interne sont indépendants du fuseau horaire à la frontière et ne deviennent conscients du fuseau horaire que lors du passage dans le convertisseur de fuseaux horaires. La sortie Intl.DateTimeFormat est sensible au paramètre régional dans la langue du navigateur de l’utilisateur ; les données sous-jacentes sont toujours ISO 8601 pour le stockage et la sérialisation.
Frequently asked questions
- Pourquoi ne pas utiliser une bibliothèque de dates comme dayjs ou date-fns ?
- Nous le faisons, en interne, pour les parties qui en bénéficient — mais chaque fonction visible dans /lib/datetime/ est écrite à partir de primitives. Les bibliothèques de dates échangent taille contre commodité, et nos mathématiques sont assez simples (et stables) pour que la dépendance ne valait pas la peine.
- Le convertisseur de fuseaux horaires gère-t-il les dates historiques ?
- Dans les limites de la portée d’IANA tzdata, oui. IANA contient des règles de transition DST remontant à environ 1970 pour la plupart des zones, et plus tôt pour un sous-ensemble. Pour les dates antérieures à 1970, le décalage retourné est le décalage moderne de la zone, qui peut être historiquement inexact. N’utilisez pas le convertisseur de fuseaux horaires pour la recherche généalogique.
Related
- Calculateur d’âge
- Différence de dates
- Jours ouvrables
- Convertisseur de fuseaux horaires
- Planificateur de réunions
- Convertisseur d’horodatage Unix
- Aide-mémoire fuseaux horaires pour équipes distantes
- Différence de dates pour les demandes de visa
- Jours ouvrables pour la facturation
- Données sur les changements DST sur 50 ans
- Glossaire : UTC
- Glossaire : ISO 8601
- Glossaire : Horodatage Unix
- Glossaire : Fuseau horaire IANA
Published May 14, 2026