Si tu as déjà stocké une date dans une base de données, conçu une API ou débogué un problème de planification qui n'apparaissait que dans certains pays, tu as probablement déjà été confronté à la relation entre le timestamp Unix et UTC. La confusion est bien réelle et provoque de véritables bugs en production. Cet article explique précisément ce qu'est UTC, pourquoi les timestamps Unix sont définis en UTC par défaut, comment fonctionnent les décalages horaires, et comment convertir correctement des timestamps en JavaScript, Python et PHP. Tu trouveras aussi les erreurs les plus courantes chez les développeurs et comment les éviter.
Table des matières
Points clés à retenir :
- Un timestamp Unix compte toujours les secondes depuis le 1er janvier 1970, 00:00:00 UTC - aucun fuseau horaire ne lui est associé.
- UTC est le point de référence universel ; l'heure locale n'est que UTC plus ou moins un décalage.
- Convertir correctement un timestamp en heure locale nécessite de connaître le fuseau horaire cible, pas seulement un décalage numérique.
- Le DST (heure d'été) modifie le décalage d'un fuseau horaire, c'est pourquoi coder des décalages en dur provoque des bugs.
Qu'est-ce qu'UTC et pourquoi c'est important ?
UTC signifie Temps Universel Coordonné. C'est la norme de temps principale qui sert de référence mondiale pour régler les horloges. Contrairement aux fuseaux horaires, UTC n'a aucun décalage - c'est le point zéro. Il ne suit pas l'heure d'été et ne change pour aucun pays ni aucune région.
Avant UTC, il y avait GMT (Greenwich Mean Time), et beaucoup de gens utilisent encore ces deux termes de façon interchangeable. Techniquement, UTC et GMT diffèrent légèrement, mais pour la plupart des usages en développement logiciel, ils sont traités comme équivalents. UTC a été formellement défini par la recommandation ITU-R TF.460 et est maintenu grâce à des horloges atomiques.
Pour les développeurs, UTC est essentiel parce qu'il fournit un point de référence unique et non ambigu. Si ton serveur à Paris et ton utilisateur à Montréal enregistrent tous les deux un événement en UTC, tu pourras toujours comparer ces deux timestamps correctement. Si chacun l'enregistre en heure locale sans métadonnées, tu as un problème.
Pourquoi les timestamps Unix sont toujours en UTC
Un timestamp Unix (aussi appelé epoch time ou POSIX time) est défini comme le nombre de secondes écoulées depuis le 1er janvier 1970, 00:00:00 UTC. Ce point d'ancrage - minuit le 1er janvier 1970 en UTC - est inscrit dans la définition même. Il n'existe pas de version de l'heure Unix qui démarrerait en heure locale de New York ou de Tokyo.
Cela signifie que la réponse à la question "est-ce qu'un timestamp Unix est toujours en UTC ?" est oui, par définition. Le nombre 1700000000 représente exactement le même instant dans le temps pour toute personne sur la planète. Ce qui change d'un utilisateur à l'autre, c'est la façon dont cet instant est affiché dans son fuseau horaire local.
Pour mieux comprendre les fondements de ce concept, consulte notre article sur l'epoch time : le fondement des timestamps Unix.
Cette conception ancrée sur UTC est l'une des propriétés les plus utiles de l'heure Unix. Parce que le nombre lui-même ne contient aucune information de fuseau horaire, deux systèmes dans des pays différents peuvent échanger un timestamp et savoir tous les deux exactement à quel instant il fait référence, sans aucune négociation supplémentaire.
UTC vs. heure locale et fuseaux horaires
UTC est la référence. L'heure locale est ce que tu obtiens en appliquant une règle de fuseau horaire par-dessus. Un fuseau horaire n'est pas simplement un décalage fixe - c'est une région nommée avec un ensemble de règles qui peuvent évoluer dans le temps (principalement à cause de l'heure d'été).
Par exemple, l'heure de Paris est UTC+1 en hiver et UTC+2 en été. Le nom du fuseau horaire est "Europe/Paris" dans la base de données des fuseaux horaires IANA, qui est la source de référence utilisée par la plupart des langages de programmation et des systèmes d'exploitation.
La conclusion pratique : quand tu stockes un timestamp Unix dans ta base de données, tu stockes une valeur UTC. Quand tu l'affiches à un utilisateur, tu le convertis dans son fuseau horaire local. Ne stocke jamais l'heure locale comme un nombre brut en supposant que c'est de l'UTC. C'est là que les bugs commencent.
Comment fonctionnent les décalages UTC
Un décalage UTC indique à quelle distance un fuseau horaire se trouve d'UTC. Il s'écrit sous la forme +HH:MM ou -HH:MM. Quelques exemples :
- UTC+02:00 - Heure d'Europe centrale d'été (CEST), utilisée en France et en Belgique pendant l'été.
- UTC-05:00 - Heure normale de l'Est (EST), utilisée sur la côte Est des États-Unis en hiver.
- UTC+05:30 - Heure normale de l'Inde (IST), qui est un décalage d'une demi-heure.
- UTC+00:00 - UTC lui-même, également utilisé par le Royaume-Uni en hiver (GMT).
Pour convertir manuellement un epoch time UTC en heure locale, tu ajoutes ou soustrais le décalage en secondes. Pour UTC+02:00, cela donne 2 * 3600 = 7200 secondes. Donc si ton timestamp Unix est 1700000000, l'heure locale en UTC+02:00 correspondrait à 1700000000 + 7200 avant le formatage.
Cependant, faire cela manuellement est risqué car les décalages changent avec l'heure d'été. Utilise toujours une bibliothèque de fuseaux horaires adaptée plutôt que de coder un décalage en dur. Consulte notre guide sur la conversion de timestamp Unix en date pour une analyse approfondie des méthodes de conversion.
Convertir des timestamps Unix en heure locale
Voici un exemple concret avec le timestamp Unix 1700000000, qui correspond au 14 novembre 2023, 22:13:20 UTC. Nous allons le convertir en heure "America/New_York" (UTC-5 en novembre) dans trois langages.
JavaScript
const ts = 1700000000;
// JavaScript Date prend des millisecondes
const date = new Date(ts * 1000);
// Affichage en heure locale de New York
const options = {
timeZone: 'America/New_York',
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
timeZoneName: 'short'
};
console.log(date.toLocaleString('fr-FR', options));
// Résultat : 14 novembre 2023 à 17:13:20 ESTNote que l'objet Date de JavaScript stocke le temps en interne sous forme de millisecondes UTC. La méthode toLocaleString avec une option timeZone gère le décalage et les règles d'heure d'été pour toi.
Python
from datetime import datetime, timezone
import zoneinfo # Python 3.9+
ts = 1700000000
# Créer un datetime UTC-aware à partir du timestamp
utc_dt = datetime.fromtimestamp(ts, tz=timezone.utc)
# Convertir en heure locale de New York
ny_tz = zoneinfo.ZoneInfo('America/New_York')
local_dt = utc_dt.astimezone(ny_tz)
print(local_dt.strftime('%Y-%m-%d %H:%M:%S %Z'))
# Résultat : 2023-11-14 17:13:20 ESTL'élément clé ici est d'utiliser datetime.fromtimestamp(ts, tz=timezone.utc). Si tu omets l'argument tz, Python utilise le fuseau horaire local de ton serveur pour interpréter le timestamp - ce qui est une source fréquente de bugs.
PHP
$ts = 1700000000;
// Créer un objet DateTime à partir du timestamp Unix (toujours UTC)
$dt = new DateTime('@' . $ts);
// Définir le fuseau horaire cible
$dt->setTimezone(new DateTimeZone('America/New_York'));
echo $dt->format('Y-m-d H:i:s T');
// Résultat : 2023-11-14 17:13:20 ESTEn PHP, le préfixe @ lors de la construction d'un objet DateTime indique à PHP de traiter la valeur comme un timestamp Unix (UTC). Sans lui, PHP peut interpréter la chaîne en utilisant le paramètre de fuseau horaire par défaut du serveur.
Erreurs fréquentes chez les développeurs
Même les développeurs expérimentés se font piéger par la gestion des fuseaux horaires. Voici les problèmes les plus courants :
1. Supposer que l'heure locale du serveur est UTC
Si ton serveur est configuré sur "Europe/Paris" et que tu appelles time() en PHP ou datetime.now() en Python sans argument de fuseau horaire, tu obtiens l'heure locale - pas UTC. Sois toujours explicite sur UTC lorsque tu enregistres des timestamps.
2. Coder des décalages UTC en dur au lieu d'utiliser des noms de fuseaux horaires
Utiliser +02:00 comme décalage fixe pour la France va poser problème en hiver quand la France passe à +01:00. Utilise toujours des fuseaux horaires nommés comme Europe/Paris pour que la bibliothèque applique automatiquement les bonnes règles d'heure d'été.
3. Stocker des timestamps comme chaînes en heure locale sans métadonnées de fuseau horaire
Une chaîne comme 2023-11-14 17:13:20 dans une base de données est ambiguë. Est-ce UTC ? EST ? CET ? Si tu stockes les timestamps sous forme d'entiers Unix ou de chaînes ISO 8601 avec un décalage UTC (par exemple, 2023-11-14T22:13:20Z), le sens est sans ambiguïté. Consulte notre comparaison entre le format timestamp Unix et ISO 8601 pour savoir lequel choisir.
4. Ignorer l'heure d'été lors de la planification
Si tu planifies une tâche pour qu'elle s'exécute "à 09h00 chaque jour" en ajoutant 86400 secondes au dernier temps d'exécution, elle dérivera d'une heure les jours où l'heure d'été change. Utilise une bibliothèque cron ou un planificateur qui comprend les règles de fuseaux horaires.
5. Confondre millisecondes et secondes
JavaScript utilise des millisecondes pour son objet Date, mais la plupart des timestamps Unix sont en secondes. Passer un timestamp en secondes à new Date() sans le multiplier par 1000 te donnera une date en janvier 1970. Ce point est traité en détail dans notre article sur secondes, millisecondes et microsecondes.
Conclusion
Les timestamps Unix et UTC sont indissociables par conception. Le timestamp est toujours une valeur UTC - un comptage de secondes depuis un point d'ancrage UTC fixe. L'heure locale n'est qu'un format d'affichage, pas un type de timestamp différent. L'approche la plus sûre est de tout stocker en UTC, de convertir en heure locale uniquement au moment de l'affichage, et de toujours utiliser des fuseaux horaires nommés plutôt que des décalages codés en dur. Respecte ces règles et la grande majorité des bugs liés aux fuseaux horaires disparaîtront simplement. Pour les bonnes pratiques de stockage de ces valeurs, consulte notre guide sur les timestamps Unix en base de données.
Convertis n'importe quel timestamp Unix en UTC ou en heure locale - instantanément
Colle n'importe quel timestamp Unix et vois-le converti en UTC et dans ton fuseau horaire local en un clic. Gratuit, sans inscription, et compatible avec les secondes et les millisecondes.
Essayer notre outil gratuit →
Oui. Par définition, un timestamp Unix epoch compte les secondes depuis le 1er janvier 1970, 00:00:00 UTC. Le nombre lui-même ne contient aucun fuseau horaire - c'est une valeur UTC. Le fuseau horaire ne devient pertinent que lorsque tu convertis le timestamp en date et heure lisibles par un humain pour l'affichage.
Utilise la bibliothèque de fuseaux horaires intégrée à ton langage. En JavaScript, utilise toLocaleString avec une option timeZone. En Python, utilise datetime.fromtimestamp(ts, tz=timezone.utc).astimezone() avec un fuseau horaire nommé. En PHP, crée un DateTime à partir du timestamp et appelle setTimezone(). Utilise toujours des fuseaux horaires nommés, pas des décalages bruts.
Cela arrive généralement parce qu'une fonction utilise le fuseau horaire par défaut du serveur au lieu d'UTC pour interpréter le timestamp. En Python, omettre l'argument tz dans datetime.fromtimestamp() utilise l'heure système locale. En PHP, ne pas utiliser le préfixe @ a le même effet. Sois toujours explicite sur UTC au moment de la création.
Un décalage UTC est le nombre d'heures (et parfois de minutes) dont un fuseau horaire est en avance ou en retard par rapport à UTC. Par exemple, UTC-05:00 est cinq heures derrière UTC. Lors de la conversion d'un timestamp Unix en heure locale, le décalage est appliqué à la valeur UTC. Comme les décalages changent avec l'heure d'été, tu dois utiliser un fuseau horaire nommé plutôt qu'un décalage codé en dur.
Oui, et c'est l'un des principaux avantages des timestamps Unix. Comme chaque timestamp est une valeur UTC, tu peux comparer directement deux timestamps sous forme d'entiers. Un nombre plus élevé correspond toujours à un instant ultérieur dans le temps, peu importe où les timestamps ont été générés. Aucune conversion de fuseau horaire n'est nécessaire pour la comparaison.