Les pubs vous déplaisent ? Aller Sans pub Auj.

Les fuseaux horaires, c'est une fausse information (et comment les gérer dans le code)

Mis à jour le

Les fuseaux horaires semblent simples des décalages UTC. Ce n'est pas le cas. Ce guide explique pourquoi les fuseaux horaires font planter le code — les trous de jour de l'heure d'été, les décalages de demi-heure, les dates naïves — et comment les gérer correctement en JavaScript, Python, PHP et SQL.

Les fuseaux horaires sont un mensonge (et comment les gérer dans le code) 1
ANNONCE · Supprimer ?

Vous avez demandé à votre serveur quelle heure il est. Il a répondu 14:00. Vous l'avez enregistré. Vous l'avez consulté à nouveau. Maintenant, il affiche 16:00. Vous n'avez rien changé. Bienvenue dans les fuseaux horaires.

Les fuseaux horaires sont l'un des problèmes les plus trompeurs en informatique. À la surface, ils semblent être une simple différence UTC — simplement ajouter ou soustraire quelques heures. En réalité, ils sont un mélange chaotique de décisions politiques, d'accidents historiques, de décalages de 30 minutes et de règles de jour de l'été qui changent sans avertissement. Cet article explique pourquoi les fuseaux horaires sont si difficiles à gérer et, plus important encore, comment les gérer correctement dans le code.

Pourquoi « Utiliser uniquement UTC » n'est qu'une moitié de la réponse

L'avis le plus courant que vous entendrez est : stocker tout en UTC. Ce conseil est correct — mais il est incomplet. Stocker en UTC résout une problème (stockage cohérent) tout en laissant un autre problème non résolu : l'affichage et l'entrée.

Un utilisateur à Tokyo planifie une réunion à 9h selon son heure locale. Vous enregistrez cela en UTC. Plus tard, un utilisateur à New York ouvre l'événement. Vous l'affichez selon son heure locale. Mais quelle heure locale s'applique quand l'utilisateur voyage ? Quand il met à jour son horloge système ? Quand le jour de l'été commence ? « Stocker en UTC, afficher en heure locale » est une politique solide — c'est la exécution qui casse la plupart des équipes.

Les vrais problèmes liés aux fuseaux horaires

Avant d'aborder les solutions, il est utile de nommer ce que vous combattez.

1. Les décalages UTC ne sont pas des fuseaux horaires

UTC+5:30 Ce n'est pas « l'heure d'Inde ». C'est un décalage statique. L'heure indienne est Asia/Kolkata — un fuseau horaire nommé qui utilise +5:30 et qui n'a jamais observé le jour de l'été. Ces deux choses sont différentes. Si vous utilisez un décalage fixe, vous stockez un nombre. Si vous stockez un fuseau nommé, vous stockez une intention.

Les fuseaux nommés existent dans la Base de données des fuseaux horaires IANA (également appelée tzdata ou la base de données Olson). Chaque langage sérieux et chaque système d'exploitation embarque une copie de cette base. Utilisez-la. Privilégiez toujours America/New_York à UTC-5.

2. Le jour de l'été déplace les heures (de manière imprévisible)

Les transitions du jour de l'été créent deux cas critiques réellement dangereux :

  • Le « saut en avance » : Les heures sautent de 2:00 à 3:00. L'heure 2:30 n'existe pas littéralement. Si vous tentez de planifier quelque chose à 2:30 ce jour-là, vous obtenez soit une erreur, soit un comportement incorrect selon votre bibliothèque.
  • Le « retour en arrière » ambigu : Les heures passent de 2:00 à 1:00. L'heure 1:30 se produit deux fois. Sans contexte supplémentaire (le drapeau de fusion), vous ne pouvez pas savoir quelle occurrence vous désignez.

Et les règles du jour de l'été changent. Des pays et des états américains ont modifié, aboli ou modifié leurs règles dans la mémoire. Le comportement de votre code dépend d'une version à jour de la base tzdata — c'est une question d'opération, pas seulement de développement.

3. Tous les décalages ne sont pas des heures entières

L'Inde est à UTC+5:30. le Népal est à UTC+5:45. Des régions de l'Australie sont à UTC+9:30. l'Iran est à UTC+3:30 en hiver et à UTC+4:30 en été. Si votre système suppose que les fuseaux horaires sont toujours à l'heure entière, il corrompra silencieusement les timestamps pour des millions d'utilisateurs.

4. L'heure locale sur un serveur n'a pas de sens

Les serveurs ont des horloges système. Ces horloges ont un fuseau horaire configuré — souvent UTC, parfois ce que le fournisseur d'hébergement a défini par défaut, parfois ce que l'administrateur système a défini il y a des années. Le code qui appelle new Date() ou datetime.now() sans spécifier un fuseau horaire repose implicitement sur cette configuration du serveur. Des environnements différents donneront des résultats différents. C'est une erreur en attente sur chaque déploiement.

L'approche correcte, par langage

JavaScript / TypeScript

L'objet natif Date dans JavaScript est un wrapper mince autour d'un timestamp en millisecondes UTC. Il semble sympathique ; il ne l'est pas. Évitez de le formater manuellement — utilisez l'API Intl.DateTimeFormat pour l'affichage, ou faites appel à une bibliothèque.

La norme moderne est Temporal — une proposition TC39 qui a été intégrée dans Chrome 121 et qui arrive dans tous les environnements principaux. Elle dispose d'un support premier pour les fuseaux horaires et est la bonne réponse à long terme :

// Store an instant (UTC-equivalent)
const meeting = Temporal.Instant.from("2025-06-15T14:00:00Z");

// Display in a specific zone
const nyTime = meeting.toZonedDateTimeISO("America/New_York");
console.log(nyTime.toString()); // 2025-06-15T10:00:00-04:00[America/New_York]

// Convert to Tokyo time
const tokyoTime = meeting.toZonedDateTimeISO("Asia/Tokyo");
console.log(tokyoTime.toString()); // 2025-06-16T23:00:00+09:00[Asia/Tokyo]

Si vous ne pouvez pas utiliser Temporal encore, date-fns-tz en combinant avec date-fns est une bonne option fiable. Luxon est une autre option solide. Moment.js est complet en fonctionnalités mais n'est plus maintenu — migrez-en.

Python

Python’s datetime Le module distingué entre les « dates naïves » (sans information de fuseau horaire) et les « dates conscientes » (avec tzinfo). Les dates naïves sont un piège — elles semblent valables mais n'ont pas de sens entre les systèmes.

Utilisez toujours des dates conscientes. Utilisez le module zoneinfo dans Python 3.9+ pour le support des fuseaux horaires IANA : Pour Python 3.8 et versions antérieures, utilisez la bibliothèque

from datetime import datetime
from zoneinfo import ZoneInfo

# Aware datetime — always do this
utc_time = datetime(2025, 6, 15, 14, 0, 0, tzinfo=ZoneInfo("UTC"))

# Convert to New York time
ny_time = utc_time.astimezone(ZoneInfo("America/New_York"))
print(ny_time)  # 2025-06-15 10:00:00-04:00

# Never do this — naive datetime, meaningless
bad = datetime(2025, 6, 15, 14, 0, 0)  # what zone is this?

— mais soyez prudent avec l'API localize/normalize de pytz qui comporte des pièges que pytzévite. zoneinfo Les classes supportent les fuseaux IANA nativement via

PHP

PHP’s DateTime et DateTimeImmutable . Privilégiez DateTimeZone— c'est plus sûr car les mutations retournent de nouveaux objets plutôt que de modifier en place. DateTimeImmutable Base de données / SQL

$utc = new DateTimeImmutable('2025-06-15T14:00:00', new DateTimeZone('UTC'));

// Convert to Sydney time
$sydney = $utc->setTimezone(new DateTimeZone('Australia/Sydney'));
echo $sydney->format('Y-m-d H:i:s T'); // 2025-06-16 00:00:00 AEST

// Store timestamps as ISO 8601 strings or Unix timestamps
echo $utc->getTimestamp(); // 1749996000

Le traitement des fuseaux horaires dans une base de données est un champ à part entière.

PostgreSQL :

  • (timestamp with time zone) — il stocke tout en UTC et le convertit à l'affichage. Ne pas utiliser Utilisez TIMESTAMPTZ (sans fuseau horaire) pour les données visibles par l'utilisateur ; il stocke ce que vous lui donnez sans conversion. TIMESTAMP MySQL :
  • est naïf (sans fuseau). Utilisez Le DATETIME si vous souhaitez stocker en UTC, mais notez que sa plage est limitée à 2038. Pour de nouvelles schémas, stocker en TIMESTAMP au format ISO 8601 ou comme un timestamp Unix dans VARCHAR est souvent plus sûr. BIGINT SQLite :
  • N'a pas de type natif de fuseau horaire. Stockez-le sous forme de texte ISO 8601 ( ) ou comme un entier Unix. Gérez la conversion dans le code de l'application.2025-06-15T14:00:00ZQuelle que soit la base de données que vous utilisez, configurez explicitement le fuseau horaire de la session plutôt que de dépendre des valeurs par défaut.

Règles pratiques qui fonctionnent réellement

Après avoir étudié la théorie, voici les règles concrètes qui empêchent la plupart des bugs liés aux fuseaux horaires :

Stockez toujours en UTC.

  1. Chaque timestamp dans votre base de données doit être en UTC. Aucune exception pour « c'est utilisé uniquement internement ». Utilisez les noms de fuseaux IANA, pas les décalages.
  2. Stockez en compagnie d'un timestamp UTC lorsque vous devez reconstruire l'heure locale initiale. Le décalage seul n'est pas récupérable après une transition du jour de l'été. America/Chicago N'appeliez jamais « maintenant » sans un fuseau horaire.
  3. — passez toujours un argument explicite de fuseau horaire ou ajoutez-le immédiatement. datetime.now(), new Date(), time() Convertissez en heure locale au dernier moment.
  4. Faites toutes les opérations de calcul en UTC. Convertissez uniquement en heure locale du moment de l'affichage. Mettez à jour votre tzdata régulièrement.
  5. Les règles des fuseaux horaires changent. Faites des mises à jour de tzdata partie de votre gestion régulière des dépendances. Testez autour des transitions du jour de l'été.
  6. Les deux dates dangereuses chaque année (saut en avance, retour en arrière) doivent être incluses dans votre ensemble de tests si vous gérez des planifications ou des données sensibles au temps. Demandez explicitement à l'utilisateur son fuseau horaire.
  7. Ne comptez pas sur la géolocalisation IP ou la détection par navigateur pour quoi que ce soit d'important. Affichez un sélecteur de fuseau horaire ; stockez le résultat. Un mot sur les timestamps Unix

Les timestamps Unix — des secondes depuis 1970-01-01T00:00:00Z — sont indépendants des fuseaux horaires par définition. Ils sont un format de stockage parfaitement valide et sont particulièrement utiles dans les journaux, les API et les caches où vous voulez un seul nombre précis.

Le problème : les timestamps Unix ne portent pas l'intention d'un utilisateur

. Si quelqu'un réserve un vol pour « le matin de Londres », et que vous stockez uniquement un timestamp Unix, vous avez perdu le fait qu'il voulait Londres. Quand le vol est rébooké trois mois plus tard et que Londres entre ou sort du BST, vous pourriez afficher la mauvaise heure locale. Stockez le fuseau horaire en même temps que le timestamp chaque fois que l'intention d'un utilisateur est importante. Le cas le plus difficile : les événements récurrentsLes événements récurrents — les réunions hebdomadaires, les cycles mensuels de facturation, les rappels quotidiens — exposent chaque cas limite des fuseaux horaires à la fois.

Considérez une règle « chaque lundi à 9h » pour un utilisateur à Los Angeles. Stockez-vous 9h en temps pacifique ? Qu'est-ce qui se passe quand ils voyagent à Tokyo ? Qu'est-ce qui se passe quand les heures sautent et que ce lundi tombe sur la date de transition ?

Le seul modèle correct est :

Stockez la règle de récurrence en heure murale + nom de fuseau : « lundi 09:00 America/Los_Angeles »

Calculez l'occurrence suivante en UTC au moment de la planification, et non au moment de la création de la règle

  • Recalculez après toute transition du jour de l'été qui tombe dans la fenêtre de récurrence
  • Des bibliothèques comme
  • (JS) et

(Python) gèrent cela correctement lorsqu'elles reçoivent le contexte approprié de fuseau horaire. Rédiger manuellement cette logique est une voie fiable vers des erreurs subtiles qui apparaissent plusieurs mois plus tard. rrule.js Les fuseaux horaires sont une fausse idée (et comment les gérer dans le code) 2 dateutil.rrule Les fuseaux horaires sont une fausse idée (et comment les gérer dans le code) 1

Envie d'une expérience sans pub ? Passez à la version sans pub

Installez nos extensions

Ajoutez des outils IO à votre navigateur préféré pour un accès instantané et une recherche plus rapide

Sur Extension Chrome Sur Extension de bord Sur Extension Firefox Sur Extension de l'opéra

Le Tableau de Bord Est Arrivé !

Tableau de Bord est une façon amusante de suivre vos jeux, toutes les données sont stockées dans votre navigateur. D'autres fonctionnalités arrivent bientôt !

ANNONCE · Supprimer ?
ANNONCE · Supprimer ?
ANNONCE · Supprimer ?

Coin des nouvelles avec points forts techniques

Impliquez-vous

Aidez-nous à continuer à fournir des outils gratuits et précieux

Offre-moi un café
ANNONCE · Supprimer ?