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)

Publié le

Les fuseaux horaires semblent simples sur une carte. Ils ne le sont pas. Voici pourquoi ils font planter logiciel — et le modèle mental correct pour les gérer dans le code.

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

Vous ouvrez une carte. Vous voyez des coupes verticales. « UTC-5 correspond à l’heure est, UTC+1 correspond à l’heure centrale européenne. » Simple, non ?

Faux. Les fuseaux horaires sont une construction politique, pas une réalité géographique — et cette distinction vous épargnera de nombreux bugs dévastateurs dans le développement logiciel.

Pourquoi les fuseaux horaires sont-ils vraiment un désordre

Voici ce que votre système d'exploitation gère discrètement à votre place dans sa base de données tz :

  • L'heure d'été (DST) — Pas tous les pays l'observent, les pays modifient les règles, et le changement a lieu le jour différent selon votre localisation. Les États-Unis ont changé leur date en 2007. L'Égypte a aboli l'heure d'été en 2011, puis l'a réintroduite, puis l'a aboli à nouveau.
  • Des écarts de 30 minutes ou 45 minutes — L'Inde (UTC+5:30), le Népal (UTC+5:45) et certaines régions de l'Australie (UTC+9:30) existent. Votre hypothèse selon laquelle les écarts sont des heures entières est fausse.
  • Des changements historiques — La Russie a passé de UTC+4 à UTC+3 en 2014. Samoâ a sauté un jour entier (30 décembre 2011) pour passer d'un côté de la ligne de date internationale à l'autre. Quand vous gérez des timestamps historiques, l'offset « correct » peut être complètement différent de celui d'aujourd'hui.
  • Des heures ambigües — Lorsque les horloges retombent, 1h30 apparaît deux fois. Lorsque les horloges avancent, 2h30 n'existe pas du tout. Si vous stockez « 3 novembre 2024 à 1h45 heure est » sans un offset UTC, vous avez un timestamp ambigüe.

Rien de cela n'est une simple curiosité. Chaque cas limite a causé des bugs réels en production — des événements manqués, des paiements doublement facturés, des systèmes de planification endommagés.

La règle unique qui résout la plupart des problèmes

Stockez et traitez en UTC. Convertissez en heure locale uniquement au moment de l'affichage.

Ceci n'est pas un conseil controversé. C'est l'avis majoritaire de chaque base de données, de chaque standard API et de chaque équipe de systèmes distribués. Si la colonne de votre base de données stocke 2024-11-03 06:45:00 en UTC, vous savez toujours exactement à quel moment dans le temps cela correspond — quel que soit le lieu de votre serveur, la zone horaire de votre utilisateur ou si l'heure d'été a eu lieu ce jour-là.

Le moment où vous stockez 2024-11-03 01:45:00 sans un offset UTC, vous perdez des informations. Vous créez un timestamp qui peut signifier deux choses différentes.

Comment gérer les fuseaux horaires en JavaScript

L'objet intégré de JavaScript stocke le temps en millisecondes depuis l'époque Unix (1er janvier 1970 UTC) — ce qui est bon. Le problème est que son API est confus et incohérent. Date Les objets stockent le temps en millisecondes depuis l'époque Unix (1er janvier 1970 UTC) — ce qui est bon. Le problème est que son API est confus et incohérent.

Ce que vous devez éviter

// BAD: Parsing without explicit timezone
const d = new Date('2024-11-03 01:45:00');
// Interpreted as LOCAL time — behavior varies by environment

// BAD: Storing user-facing strings as dates
const meeting = '3:00 PM Thursday';
// This is meaningless without a timezone

Ce que vous devez utiliser au lieu de cela

// GOOD: Always use ISO 8601 with explicit UTC offset
const d = new Date('2024-11-03T06:45:00Z'); // Z = UTC

// GOOD: Display in user's local timezone using Intl API
const formatter = new Intl.DateTimeFormat('en-US', {
  timeZone: 'America/New_York',
  dateStyle: 'full',
  timeStyle: 'short',
});
console.log(formatter.format(d)); // "Sunday, November 3, 2024 at 1:45 AM"

Si vous construisez quelque chose de plus complexe que la simple mise en forme de dates, utilisez la Luxon bibliothèque. Elle dispose d'un support intégré des fuseaux horaires, gère correctement les transitions de l'heure d'été et rend clair l'intention de votre code.

import { DateTime } from 'luxon';

// Parse an ISO string and convert to a specific zone
const utc = DateTime.fromISO('2024-11-03T06:45:00Z');
const eastern = utc.setZone('America/New_York');
console.log(eastern.toLocaleString(DateTime.DATETIME_FULL));
// "November 3, 2024, 1:45 AM EDT"

Comment gérer les fuseaux horaires en Python

Python’s datetime module distingue entre naïf (sans fuseau horaire) et conscient (avec fuseau horaire) des objets datetime. Les datetimes naïfs sont un piège — évitez-les dans tout code qui traverse des fuseaux horaires.

from datetime import datetime, timezone
import zoneinfo  # Python 3.9+

# BAD: naive datetime (no timezone info)
d = datetime(2024, 11, 3, 1, 45, 0)

# GOOD: always attach a timezone
d_utc = datetime(2024, 11, 3, 6, 45, 0, tzinfo=timezone.utc)

# Convert to a specific timezone
eastern = zoneinfo.ZoneInfo('America/New_York')
d_eastern = d_utc.astimezone(eastern)
print(d_eastern)  # 2024-11-03 01:45:00-05:00

Pour des versions anciennes de Python ou des besoins de planification plus complexes, python-dateutil et Flèche sont des choix bien maintenus. Le principe clé reste le même : travailler en UTC, convertir au niveau de la frontière.

Comment gérer les fuseaux horaires dans les bases de données

Le traitement des fuseaux horaires dans les bases de données déconcerte même les développeurs expérimentés.

PostgreSQL

PostgreSQL dispose de deux types de timestamps : timestamp (sans fuseau horaire) et timestamptz (avec fuseau horaire). Bien que le nom le suggère, timestamptz ne stocke pas réellement le fuseau horaire — il convertit en UTC lors de l'écriture et le convertit en retour vers le fuseau horaire de la session lors de la lecture. C'est le comportement correct. Utilisez toujours timestamptz.

-- BAD
CREATE TABLE events (created_at TIMESTAMP);

-- GOOD
CREATE TABLE events (created_at TIMESTAMPTZ);

-- Querying across timezones
SELECT created_at AT TIME ZONE 'America/New_York' FROM events;

MySQL

MySQL’s DATETIME qui stocke sans contexte de fuseau horaire — ce que vous mettez est ce que vous obtenez, sans conversion. TIMESTAMP convertit en UTC lors de l'écriture et en retour vers le fuseau horaire actuel du serveur lors de la lecture — mais elle est limitée aux dates entre 1970 et 2038 (le dépassement de l'horodatage Unix). En pratique : utilisez DATETIME colonnes et assurez-vous que votre application écrit toujours des valeurs en UTC explicitement.

Planification à travers les fuseaux horaires : le piège caché

Supposons qu'un utilisateur planifie une réunion hebdomadaire récurrente à « chaque lundi à 9h heure de New York ». Vous stockez le prochain événement sous forme d'un timestamp UTC. C'est bon — jusqu'au changement de l'heure d'été, et maintenant le timestamp UTC que vous avez stocké correspond à 10h à New York au lieu de 9h.

La solution : ne pas stocker des timestamps absolus futurs pour les événements récurrents. Stockez la règle locale — l'identifiant de fuseau horaire + l'heure locale — et calculez le prochain timestamp UTC en temps réel. Ainsi, le système recalculera correctement après les transitions de l'heure d'été.

-- Store the intent, not the absolute moment
CREATE TABLE recurring_events (
  id SERIAL PRIMARY KEY,
  timezone TEXT NOT NULL,       -- 'America/New_York'
  local_time TIME NOT NULL,     -- '09:00:00'
  recurrence TEXT NOT NULL      -- 'WEEKLY:MONDAY'
);
-- Compute next_occurrence_utc in application code at dispatch time

Noms des fuseaux horaires IANA versus écarts UTC

Lorsque vous stockez la préférence de fuseau horaire d'un utilisateur, stockez le nom IANA (America/New_York, Europe/London, Asia/Kolkata) — pas l'écart UTC (UTC-5, UTC+1). Les écarts sont des instantanés ; les noms IANA encodent l'histoire complète de l'heure d'été et les règles futures.

America/New_York est UTC-5 en hiver et UTC-4 en été. Si vous stockez UTC-5, vous intégrez l'erreur d'écarts pendant la moitié de l'année.

Référence rapide : les règles

  • Stockez les timestamps en UTC — toujours, sans exception dans votre base de données ou dans vos réponses API.
  • Utilisez les noms IANA des fuseaux horaires — pas les écarts UTC — pour les préférences des utilisateurs et les plans récurrents.
  • N'analysez jamais des chaînes de dates sans un fuseau horaire explicite — le comportement implicite dépend de l'environnement.
  • Convertissez en heure locale au niveau de l'affichage — pas dans votre logique métier ou vos requêtes de base de données.
  • Pour les plans récurrents, stockez la règle — pas le timestamp UTC précalculé — afin que les transitions de l'heure d'été ne corrompent pas les occurrences futures.
  • Testez avec des cas extrêmes — l'heure de transition de l'heure d'été, les dates proches de la ligne de date internationale, et les timestamps historiques dans des régions ayant changé leurs écarts.
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 ?