Les horodatages Unix sont l’un des formats de données les plus importants en programmation. On les trouve dans les enregistrements de bases de données, les réponses d’API, les journaux, les métadonnées du système de fichiers, les jetons d’authentification et bien d’autres endroits. Le format est d’une grande simplicité : un entier unique qui représente les secondes (ou millisecondes, microsecondes ou nanosecondes) écoulées depuis le 1er janvier 1970. Pourtant, leur utilisation correcte est étonnamment délicate à cause des fuseaux horaires, des écarts de précision entre systèmes et des cas limites liés au changement d’heure. Les sections suivantes expliquent ce qu’est le temps Unix et pourquoi il existe, comment gérer correctement les fuseaux horaires lors des conversions et quelles erreurs peuvent encore piéger des développeurs expérimentés.
Qu’est-ce que le temps Unix et pourquoi existe-t-il ?
Le temps Unix, également appelé temps Epoch ou temps POSIX, correspond au nombre de secondes écoulées depuis le 1er janvier 1970 à 00:00:00 UTC, point de référence appelé époque Unix. Les valeurs négatives représentent les dates antérieures à cette époque et les valeurs positives les dates postérieures. Le format est apparu au début des années 1970, lorsque les systèmes Unix avaient besoin d’un moyen compact et indépendant des fuseaux horaires pour stocker les horodatages dans les métadonnées du système de fichiers et les journaux. Un seul entier signé de 32 bits pouvait représenter des dates de 1901 à 2038, plage qui semblait suffisante à l’époque mais qui est à l’origine du célèbre problème de l’an 2038. Les systèmes modernes utilisent des entiers de 64 bits, repoussant l’échéance à l’année 292 milliards. L’élégance du temps Unix tient à l’absence de fuseau horaire, de changement d’heure, de secondes intercalaires (en théorie ; la plupart des implémentations étalent simplement ces rares secondes) et de complexité de calendrier. Il s’agit d’un compteur croissant qui désigne sans ambiguïté un instant précis. Les fuseaux horaires, les dates du calendrier et les formats lisibles par les humains ne sont appliqués qu’au moment de l’affichage. Le temps Unix est ainsi privilégié pour les comparaisons (`if (tokenExpiresAt < now)`), le tri et le stockage d’horodatages dans des bases de données réparties entre plusieurs fuseaux horaires. Les formats lisibles comme `2024-04-21 11:58:41` sont dérivés de la valeur Unix stockée uniquement au moment de l’affichage.
Gestion des fuseaux horaires : la partie subtile
Un horodatage Unix n’a pas de fuseau horaire : il représente un instant absolu. Pour le convertir en une forme lisible, vous choisissez le fuseau d’affichage ; un même horodatage donne alors des heures locales différentes selon la zone. Par exemple, 1,713,711,521 secondes après l’époque Unix correspondent à 15:58:41 UTC, mais au même instant à 11:58:41 EDT (America/New_York, UTC-4), 08:58:41 PDT (America/Los_Angeles, UTC-7), 00:58:41 JST le lendemain (Asia/Tokyo, UTC+9) et à d’innombrables autres heures locales dans le monde. En pratique, il faut utiliser des noms de fuseaux horaires IANA comme `America/New_York` plutôt que des décalages fixes comme `UTC-05:00`, car les noms IANA encodent l’historique complet des changements d’heure. Dire « 16 h EST le 15 juillet 2024 » est ambigu : l’heure de l’Est observe le changement saisonnier et, en juillet, il s’agit de l’EDT (UTC-4), pas de l’EST (UTC-5). Les fuseaux IANA règlent automatiquement cette ambiguïté. L’API Intl du navigateur, ainsi que des bibliothèques côté serveur comme pytz, moment-timezone et ZoneId de Java, utilisent la base IANA et gèrent correctement les transitions historiques. Ce convertisseur s’appuie sur Intl.DateTimeFormat intégré au navigateur et prend en charge l’ensemble des fuseaux IANA. Il fournit ainsi l’heure locale correcte pour toute zone valide, y compris pour les dates historiques remontant à 1970 ou avant.
Erreurs courantes qui piègent même les développeurs expérimentés
Quelques erreurs liées aux horodatages sont si fréquentes qu’il vaut la peine de les garder en tête. Premièrement, la confusion entre secondes et millisecondes : l’objet Date de JavaScript utilise les millisecondes, tandis que time.time() de Python utilise les secondes. Les mélanger multiplie ou divise les dates par 1,000. Vérifiez l’ordre de grandeur : 10 chiffres correspondent à des secondes, 13 à des millisecondes et 16 à des microsecondes. Deuxièmement, les hypothèses de fuseau horaire lors de l’analyse d’une chaîne : « 2024-04-21 11:58:41 » n’en précise aucun, et les analyseurs peuvent adopter des valeurs par défaut différentes. Le constructeur Date de JavaScript l’interprète comme une heure locale ; datetime.fromisoformat de Python la traite comme une valeur naïve, sans fuseau horaire. Avant d’analyser une chaîne ambiguë, associez-lui toujours un fuseau explicite. Troisièmement, les cas limites liés au changement d’heure au printemps et à l’automne : dans la plupart des fuseaux horaires américains, 2 h 30 le jour du passage à l’heure d’été n’existe pas (l’horloge passe de 1 h 59 à 3 h), tandis que 1 h 30 le jour du retour à l’heure standard se produit deux fois. Les opérations qui ajoutent ou retranchent des heures à travers une transition peuvent produire des résultats surprenants si vous n’utilisez pas de bibliothèques tenant compte des fuseaux IANA. Quatrièmement, le décalage de « maintenant » entre serveurs : leurs horloges peuvent différer de quelques millisecondes ou secondes ; les jetons créés sur un serveur et validés sur un autre nécessitent donc une marge de tolérance. Cinquièmement, les secondes intercalaires : rarement importantes en pratique, puisque la plupart des systèmes les étalent, mais cruciales pour certaines applications scientifiques ou financières. Ce convertisseur évite la plupart de ces problèmes grâce aux API Intl éprouvées du navigateur. Ces notions restent toutefois importantes lorsque vous écrivez du code qui exploite les valeurs converties.