timestamp unix time date converter

Convertisseur de Timestamp Unix : Traduisez le temps Epoch en dates lisibles

Convertissez les timestamps Unix en dates lisibles par l'homme et vice versa. Un outil essentiel pour les développeurs travaillant avec le temps epoch et les formats de date.

Introduction

Un Unix timestamp est l'un des concepts les plus fondamentaux en informatique. Il représente un moment précis dans le temps sous forme d'entier simple — le nombre de secondes écoulées depuis l'epoch Unix (1er janvier 1970, 00:00:00 UTC). Ce format simple et universel sous-tend tout, des enregistrements de bases de données et réponses d'API aux fichiers journaux et tâches planifiées.

Contrairement aux chaînes de date lisibles par les humains comme "9 avril 2024", un Unix timestamp n'a ni fuseau horaire, ni locale, ni ambiguïté. Le nombre 1712620800 désigne exactement le même moment partout sur Terre. Cette propriété en fait la lingua franca des dates et heures en génie logiciel.

Histoire de l'Epoch Unix

Le système d'exploitation Unix a été développé aux Bell Labs à la fin des années 1960 et au début des années 1970 par Ken Thompson, Dennis Ritchie et leurs collègues. Le suivi du temps était intégré au noyau dès le début, mais le choix exact de la date d'epoch a évolué pendant le développement précoce.

Certaines des premières versions d'Unix utilisaient le 1er janvier 1971 comme epoch. D'autres ont expérimenté avec le 1er janvier 1969. Finalement, le 1er janvier 1970, 00:00:00 UTC a été standardisé — une date "ronde" suffisamment proche de la création du système pour que les timestamps des événements réels soient de petits entiers positifs.

Le choix du 1er janvier 1970 est, en essence, arbitraire. Ce qui importe n'est pas la date elle-même, mais la cohérence de la convention. Comme tous les systèmes s'accordent sur le même epoch, les timestamps peuvent être échangés entre programmes, langages et plateformes sans aucune surcharge de conversion.

Cette convention a été ensuite formalisée dans POSIX (Portable Operating System Interface), qui définit un Unix timestamp comme le nombre de secondes non-bissextiles depuis 1970-01-01T00:00:00Z.

Secondes vs. Millisecondes

Tous les "timestamps" ne sont pas identiques. La distinction la plus importante est l'unité :

  • Unix timestamp (POSIX) : secondes depuis l'epoch — ex. : 1712620800
  • JavaScript Date : millisecondes depuis l'epoch — ex. : 1712620800000
  • Java System.currentTimeMillis() : millisecondes depuis l'epoch
  • Go time.Now().Unix() : secondes ; time.Now().UnixNano() donne des nanosecondes
  • Python time.time() : secondes en virgule flottante

La différence d'un facteur 1000 entre secondes et millisecondes est une source fréquente de bugs. Passer un timestamp en millisecondes à du code qui attend des secondes produit une date dans un futur lointain (année ~56 000) ; l'inverse produit une date en janvier 1970.

La conversion est simple :

const unix_ms = unix_s * 1000;
const unix_s  = Math.floor(unix_ms / 1000);

Une règle pratique : si votre timestamp est un nombre à 10 chiffres, il est probablement en secondes. S'il a 13 chiffres, il est probablement en millisecondes.

Format ISO 8601 et Variantes

ISO 8601 est le standard international pour représenter les dates et heures. Il définit une famille de formats de chaînes non ambigus :

2024-04-09                        # Date seulement
2024-04-09T12:00:00               # Date/heure locale (pas d'info de fuseau)
2024-04-09T12:00:00Z              # UTC (Z = heure Zulu = UTC+0)
2024-04-09T20:00:00+08:00         # Avec décalage UTC (ex. : Asia/Shanghai)
2024-04-09T12:00:00.123Z          # Avec millisecondes
2024-04-09T12:00:00.123456789Z    # Avec nanosecondes

Le T sépare les parties date et heure. Le suffixe Z (de "Zulu", l'alphabet phonétique OTAN pour UTC) signifie que l'heure est en UTC. Un décalage comme +08:00 signifie que l'heure locale est 8 heures en avance sur UTC.

ISO 8601 est le format recommandé pour les APIs REST, les fichiers journaux et tout système qui échange des données temporelles entre systèmes. Il est lisible par les humains, triable lexicographiquement comme chaîne, et non ambigu.

Fuseaux Horaires et UTC

UTC (Temps Universel Coordonné) est le principal standard de temps mondial. Ce n'est pas un fuseau horaire en soi, mais la référence à partir de laquelle tous les fuseaux horaires sont définis. UTC+0 est équivalent au Greenwich Mean Time (GMT) en hiver.

Les fuseaux horaires sont exprimés en décalages par rapport à UTC : UTC+5:30 (Inde), UTC-8 (Heure Standard du Pacifique US), UTC+9 (Japon). Cependant, les décalages bruts ne suffisent pas à décrire complètement un fuseau horaire, car les décalages changent avec l'heure d'été (DST).

La base de données de fuseaux horaires IANA (aussi appelée base de données tz ou zoneinfo) est la liste de référence de tous les fuseaux horaires mondiaux. Elle utilise des identifiants comme America/New_York, Europe/Paris, Asia/Tokyo et Europe/Zurich. Ces identifiants encapsulent non seulement le décalage UTC actuel mais l'historique complet des règles DST et des changements politiques.

Tous les principaux langages de programmation et systèmes d'exploitation incluent la base de données IANA :

  • JavaScript (Node.js) : Intl.DateTimeFormat avec des identifiants IANA
  • Python : module zoneinfo (Python 3.9+) ou pytz
  • Java : java.time.ZoneId (ex. : ZoneId.of("Europe/Paris"))
  • Go : time.LoadLocation("Europe/Paris")

N'utilisez jamais des décalages UTC bruts comme +01:00 pour représenter des fuseaux horaires dans la logique applicative. Utilisez des identifiants IANA à la place, car les décalages changent saisonnièrement.

Complications de l'Heure d'Été (DST)

L'heure d'été (DST) est la pratique d'avancer les horloges d'une heure pendant les mois d'été pour prolonger la lumière du jour en soirée. Elle est observée dans la majeure partie de l'Amérique du Nord et de l'Europe, et dans certaines parties de l'Amérique du Sud, du Moyen-Orient et de l'Océanie. De nombreux pays, dont le Japon, la Chine et l'Inde, n'observent pas du tout l'heure d'été.

Le DST introduit deux anomalies classiques :

Passage à l'heure d'été (Spring forward) : Les horloges sautent de 2h00 directement à 3h00. La fenêtre de 60 minutes entre 2h00 et 3h00 n'existe jamais en heure locale. Si vous planifiez une tâche à 2h30, elle s'exécute à 3h30 ou est complètement ignorée, selon le planificateur.

Retour à l'heure d'hiver (Fall back) : Les horloges reviennent de 2h00 à 1h00. La fenêtre de 60 minutes entre 1h00 et 2h00 se produit deux fois. Si vous enregistrez une entrée de journal à "1h45 heure locale", elle est ambiguë — elle pourrait provenir de la première ou de la deuxième occurrence de cette heure.

Les Unix timestamps sont entièrement immunisés contre le DST car ils sont toujours relatifs à UTC. Le nombre 1712620800 désigne toujours le même instant, peu importe où vous êtes ou quelle saison c'est.

La règle d'or : stockez et transmettez toujours les timestamps en UTC. Convertissez en heure locale uniquement dans la couche de présentation, immédiatement avant d'afficher à un utilisateur humain.

Le Problème de l'An 2038

Le Problème de l'An 2038 (aussi appelé Y2K38 ou le Bug du Millénaire Unix) est une vulnérabilité logicielle similaire dans sa nature au bug de l'an 2000.

La cause profonde : de nombreux systèmes legacy stockent les Unix timestamps sous forme d'entier signé 32 bits. La valeur maximale d'un entier signé 32 bits est 2 147 483 647. Cela correspond à :

2038-01-19 03:14:07 UTC

Une seconde après ce moment, un entier signé 32 bits déborde et revient à la valeur la plus négative : -2 147 483 648, qui correspond au 1901-12-13 20:45:52 UTC. Les systèmes qui débordent croiront soudainement que la date est en 1901.

Systèmes potentiellement affectés :

  • Systèmes embarqués legacy et appareils IoT compilés pour des architectures 32 bits
  • Anciens schémas de bases de données utilisant le type TIMESTAMP de MySQL (utilisait un stockage 32 bits dans les versions antérieures à 8.0)
  • Noyaux Linux 32 bits (résolu dans le noyau pour les plateformes 64 bits)
  • Certains anciens systèmes de fichiers qui enregistrent les temps de modification comme des entiers 32 bits

La solution est simple : migrer tout le stockage de timestamps vers des entiers signés 64 bits. Un timestamp 64 bits peut représenter des dates jusqu'à environ l'an 292 277 026 596 — bien au-delà de toute préoccupation pratique. La plupart des systèmes modernes 64 bits gèrent déjà cela correctement.

Travailler avec les Timestamps dans Différents Langages

JavaScript

// Heure actuelle
const now = Date.now();                   // millisecondes depuis l'epoch
const unix = Math.floor(now / 1000);      // convertir en secondes

// Parser un Unix timestamp
const date = new Date(unix * 1000);
console.log(date.toISOString());          // "2024-04-09T12:00:00.000Z"
console.log(date.toLocaleString("fr-FR", { timeZone: "Europe/Paris" }));

Python

import time
import datetime

# Unix timestamp actuel (secondes)
unix = int(time.time())

# Convertir en datetime UTC
dt = datetime.datetime.fromtimestamp(unix, tz=datetime.timezone.utc)
print(dt.isoformat())   # "2024-04-09T12:00:00+00:00"

# Utiliser zoneinfo pour le fuseau horaire IANA
from zoneinfo import ZoneInfo
dt_local = dt.astimezone(ZoneInfo("Europe/Paris"))
print(dt_local.isoformat())

Go

package main

import (
    "fmt"
    "time"
)

func main() {
    unix := time.Now().Unix()           // int64 secondes
    t := time.Unix(unix, 0).UTC()
    fmt.Println(t.Format(time.RFC3339)) // "2024-04-09T12:00:00Z"

    loc, _ := time.LoadLocation("Europe/Paris")
    fmt.Println(t.In(loc).Format(time.RFC3339)) // "2024-04-09T14:00:00+02:00"
}

Java

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;

long unix = Instant.now().getEpochSecond();        // secondes
Instant instant = Instant.ofEpochSecond(unix);
System.out.println(instant.toString());            // "2024-04-09T12:00:00Z"

ZonedDateTime zdt = instant.atZone(ZoneId.of("Europe/Paris"));
System.out.println(zdt.toString());

Rust

use std::time::{SystemTime, UNIX_EPOCH};

fn main() {
    let unix = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .expect("Le temps est revenu en arrière")
        .as_secs();   // u64 secondes

    println!("{}", unix);  // ex. : 1712620800
}

Tableau des Formats de Timestamp Courants

Format Exemple Utilisé dans
Unix (secondes) 1712620800 Unix/Linux, APIs POSIX
Unix (millisecondes) 1712620800000 JavaScript, Java
Unix (microsecondes) 1712620800000000 PostgreSQL, certaines APIs
Unix (nanosecondes) 1712620800000000000 Go, Rust
ISO 8601 UTC 2024-04-09T12:00:00Z APIs REST, bases de données
ISO 8601 avec offset 2024-04-09T20:00:00+08:00 Applications de calendrier
RFC 2822 Tue, 09 Apr 2024 12:00:00 +0000 En-têtes d'email
RFC 3339 2024-04-09T12:00:00Z Protocoles Internet
Date HTTP Tue, 09 Apr 2024 12:00:00 GMT En-têtes HTTP

Arithmétique des Timestamps

Comme un Unix timestamp est simplement un nombre, l'arithmétique sur les timestamps est triviale.

Calculer la durée entre deux timestamps :

start = 1712620800
end   = 1712707200
duree_secondes = end - start   # 86400 secondes = exactement 1 jour

Trouver une date future ou passée :

const now = Math.floor(Date.now() / 1000);
const uneSemainePlus  = now + 7 * 24 * 60 * 60;   // +604800 secondes
const trenteJoursAvant = now - 30 * 24 * 60 * 60; // -2592000 secondes

Durées courantes en secondes :

Durée Secondes
1 minute 60
1 heure 3 600
1 jour 86 400
1 semaine 604 800
30 jours 2 592 000
1 an (365 jours) 31 536 000

Note : pour l'arithmétique tenant compte du calendrier (ex. : "ajouter 1 mois"), utilisez une bibliothèque de dates plutôt que des secondes brutes, car les mois ont des longueurs différentes et le DST peut rendre certains jours de 23 ou 25 heures.

Cas d'Usage

Journalisation d'application : Les entrées de journal avec des Unix timestamps peuvent être triées, filtrées et comparées entre systèmes distribués fonctionnant dans différents fuseaux horaires — le tout sans ambiguïté.

APIs REST : Renvoyer des timestamps sous forme d'entiers Unix évite l'interprétation du fuseau horaire côté serveur. Le client lit l'entier et le formate dans le fuseau horaire local de l'utilisateur.

Bases de données : Stocker les timestamps comme entiers (ou chaînes ISO 8601) est plus portable que les types de date spécifiques à la plateforme. Le TIMESTAMPTZ de PostgreSQL stocke en interne en UTC ; le DATETIME de MySQL (préféré à TIMESTAMP) évite la limite Y2038.

Tâches planifiées et cron : Calculer "exécuter à 3h00 tous les jours" en UTC évite les surprises du DST. De nombreux frameworks de planification (Kubernetes CronJobs, planifications GitHub Actions) utilisent UTC par convention.

Expiration de cache et TTL : Les en-têtes HTTP Cache-Control: max-age=3600 et Expires utilisent des Unix timestamps absolus ou des secondes relatives ; les CDNs et navigateurs s'appuient sur une arithmétique précise des timestamps pour invalider les caches.

Event sourcing et pistes d'audit : Les journaux d'événements immuables nécessitent des timestamps qui ordonnent sans ambiguïté les événements. Les Unix timestamps, notamment à résolution nanosecondes, offrent cette garantie même pour les systèmes à haut débit.

Bonnes Pratiques

  1. Toujours stocker les timestamps en UTC. Ne jamais stocker l'heure locale dans une base de données. Convertir en heure locale uniquement dans la couche de présentation.

  2. Utiliser des entiers 64 bits. Éviter int32 pour les timestamps dans tout nouveau code. Même si votre système ne traite actuellement que des dates dans un futur proche, 64 bits est la valeur par défaut sûre.

  3. Utiliser ISO 8601 pour la sérialisation lisible par les humains. Lorsque vous avez besoin d'une représentation en chaîne dans les journaux ou les APIs, ISO 8601 est non ambigu et triable lexicographiquement.

  4. Utiliser des identifiants de fuseau horaire IANA, pas des offsets. "Europe/Paris" est correct ; "+01:00" est fragile car l'offset change deux fois par an.

  5. Valider les unités de timestamp. Avant d'utiliser un timestamp externe, vérifiez s'il est en secondes, millisecondes ou autre unité. Une vérification rapide : un nombre à 10 chiffres est probablement en secondes ; 13 chiffres est probablement en millisecondes.

  6. Ne jamais parser des dates avec des expressions régulières en code de production. Utilisez la bibliothèque standard de votre langage ou une bibliothèque tierce bien testée.

  7. Attention à "minuit". Dans les fuseaux horaires qui observent le DST, minuit peut ne pas exister à certaines dates (transitions de passage à l'heure d'été). Utilisez midi (12:00 UTC) comme heure "représentative" sûre pour les calculs de date seule.

  8. Tester autour des transitions DST. Si votre application implique de la planification ou des calculs de temps, écrivez des tests qui exercent spécifiquement les limites du passage à l'heure d'été et du retour à l'heure d'hiver pour les fuseaux horaires concernés.

Foire Aux Questions (FAQ)

Q : Que représente le Unix timestamp 0 ?
R : Le 1er janvier 1970, 00:00:00 UTC — l'epoch Unix. Les timestamps négatifs représentent des dates antérieures à 1970.

Q : Puis-je utiliser les timestamps pour trier ?
R : Oui. Comme un Unix timestamp est un entier monotoniquement croissant, trier par timestamp est équivalent à trier chronologiquement.

Q : Le temps Unix est-il affecté par les secondes intercalaires ?
R : POSIX définit le temps Unix comme si chaque jour avait exactement 86 400 secondes, ce qui signifie que les secondes intercalaires ne sont pas comptées. Un timestamp POSIX est techniquement "temps Unix" ou "temps POSIX", pas le "vrai" Temps Atomique International (TAI). En pratique, cela importe rarement pour le code applicatif.

Q : Quelle est la date maximale représentable avec un Unix timestamp ?
R : Avec un entier signé 64 bits, le maximum correspond à l'an 292 277 026 596. Avec un entier signé 32 bits, c'est le 2038-01-19 03:14:07 UTC.

Q : Comment obtenir le Unix timestamp actuel dans mon navigateur ?
R : Math.floor(Date.now() / 1000) dans la console du navigateur renvoie le Unix timestamp actuel en secondes.

Q : Pourquoi mon timestamp affiche-t-il 1970-01-01 quand je le convertis ?
R : Vous passez très certainement des millisecondes à une fonction qui attend des secondes (ou vice versa). Divisez par 1000 si vous voyez une date dans un futur lointain ; multipliez par 1000 si vous voyez le 1er janvier 1970.