Tout système qui stocke un instant finit par se poser la même question : ce nombre est-il en secondes ou en millisecondes ? Les horodatages Unix paraissent triviaux — un entier qui compte les secondes écoulées depuis le 1ᵉʳ janvier 1970 — et c’est précisément pour cela qu’on les manipule mal. Une valeur fausse d’un facteur 1000, une date en 1970, un décalage de fuseau qui n’apparaît que chez les utilisateurs de l’autre hémisphère : tout vient des mêmes malentendus.
Cet article explique ce que mesure réellement un horodatage Unix, comment distinguer secondes et millisecondes, comment l’ISO 8601 s’insère dans le tableau et comment convertir d’un format à l’autre sans deviner.
Ce qu’un horodatage Unix est réellement
Un horodatage Unix — aussi appelé époque — est le nombre de secondes écoulées depuis le 00:00:00 UTC du 1ᵉʳ janvier 1970, l’époque Unix. C’est un entier sans fuseau horaire : le même nombre décrit le même instant partout dans le monde.
N’ayant pas de fuseau, l’époque est un format d’échange naturel pour les machines. Les API, les journaux, les bases de données et les files de messages stockent des horodatages ; les humains lisent des dates. La conversion entre les deux est là où vivent les erreurs.
Notez ce qu’un horodatage ne contient pas : un fuseau, une locale, un calendrier. 1758537600 est un instant. Qu’un Bangkok voie 21 h et un Paris 14 h dépend uniquement de la manière dont vous le présentez.
Secondes vs millisecondes : l’erreur la plus fréquente
Deux conventions coexistent et on les trouve partout :
- Secondes — aujourd’hui 10 chiffres, par exemple
1758537600. L’Unix historique,Unix()de Go,getEpochSecond()de Java, Redis et la plupart des bases de données utilisent cette unité. - Millisecondes — 13 chiffres, par exemple
1758537600000.Date.now()de JavaScript,getTime()de Java et la plupart des API navigateur utilisent cette unité.
Confondre les unités fait sauter la date en 1970 ou 2286. Il n’existe pas de règle universelle pour deviner l’unité : la voie fiable consiste à connaître le contrat de la source. Si vous devez deviner, 10 chiffres sont en général des secondes et 13 des millisecondes — mais deviner est l’erreur, pas la solution.
Règle : stockez l’unité à côté de la valeur. Utilisez un nom de colonne (created_at_ms), un champ d’API explicite ou une propriété unit. Tout vaut mieux qu’un entier nu appelé time.
ISO 8601 : le côté lisible par les humains
Les chaînes ISO 8601 sont le pendant des nombres d’époque : lisibles, triables en UTC et non ambiguës lorsqu’elles portent un décalage.
2026-09-22T14:00:00Z # UTC, indiqué par le Z final
2026-09-22T14:00:00+02:00 # le même instant, heure locale de Berlin
2026-09-22T14:00:00.123Z # conserve les millisecondes
Le Z final et le décalage numérique ne sont pas des décorations. Sans l’un ou l’autre, la chaîne n’a pas de fuseau et votre code doit deviner — et c’est ainsi qu’« heure identique » devient silencieusement un décalage de trois heures.
Fuseaux horaires et UTC
Stoquez et comparez en UTC, et convertissez vers un fuseau local dans la couche de présentation, uniquement pour l’affichage humain.
const now = Date.now(); // millisecondes depuis l’époque
const seconds = Math.floor(now / 1000); // secondes depuis l’époque
new Date(seconds * 1000).toISOString(); // "2026-09-22T14:00:00.000Z"
Deux règles évitent la plupart des problèmes de fuseau :
- Ne comparez jamais une heure locale naïve à une autre. Sérialisez d’abord les deux en instants, puis comparez.
- Gardez le décalage à côté de la valeur quand le fuseau de l’utilisateur compte (rendez-vous, plannings, périodes de facturation). Un instant en UTC plus un identifiant IANA comme
Europe/Parisvaut mieux qu’un décalage fixe, car les décalages fixes changent avec l’heure d’été.
Aide-mémoire de conversion
| Convertir | JavaScript | Python |
|---|---|---|
| Millisecondes en chaîne de date | new Date(1758537600000).toISOString() |
datetime.fromtimestamp(1758537600, tz=timezone.utc) |
| Chaîne de date en secondes | Math.floor(Date.parse(s) / 1000) |
int(dt.replace(tzinfo=timezone.utc).timestamp()) |
| Secondes en millisecondes | seconds * 1000 |
seconds * 1000 |
| Heure actuelle | Date.now() (millisecondes) |
int(time.time()) (secondes) |
Notez que Date.now() renvoie des millisecondes quand time.time() renvoie des secondes : l’illustration compacte du fait que l’unité est une convention propre à chaque langage, pas un standard universel.
Les erreurs à éviter
- Multiplier par 1000 « par sécurité ». Décidez d’après le contrat, jamais d’après le nombre de chiffres.
- Stocker une heure locale sans décalage. L’heure d’été cassera l’arithmétique tôt ou tard.
- Parser en découpant des chaînes. Utilisez le parseur de la bibliothèque standard : ISO 8601 apporte semaine, format abrégé et fractionnaires que le code maison fait échouer.
- Des formats de date dans SQL. Gardez la valeur numérique ou en UTC en base et formatez dans l’application, où vous contrôlez locale et fuseau.
- Utiliser l’horodatage complet comme référence humaine. Quand on le lit à voix haute, on lâche des chiffres. Réduisez ou hachez si vous avez besoin d’une référence courte.
À essayer
Collez une valeur d’époque ou une chaîne de date dans un convertisseur d’horodatages pour passer entre secondes, millisecondes, ISO 8601 et votre heure locale. La conversion se fait dans votre navigateur : aucun horodatage — sensible ou non — n’a besoin de quitter votre machine pour être lisible.