8 min

Formatage et conversion du temps en JavaScript : pièges courants

Apprenez à formater et convertir les dates en JavaScript sans surprises : timestamps, chaînes ISO, fuseaux horaires, DST, règles d'analyse et bonnes pratiques fiables.

Formatage et conversion du temps en JavaScript : pièges courants

Ce qui tourne généralement mal avec l'heure en JavaScript

Les bugs liés au temps en JavaScript n'apparaissent que rarement comme « l'horloge est fausse ». Ils se manifestent par de petits décalages confus : une date correcte sur votre portable mais erronée sur la machine d'un collègue, une réponse d'API qui semble juste jusqu'à ce qu'elle soit rendue dans un autre fuseau horaire, ou un rapport « déréglé » autour d'un changement de saison.

Les symptômes les plus courants

Vous remarquerez généralement un (ou plusieurs) de ces cas :

  • Décalage d'une heure : surtout autour de l'heure d'été, ou lorsqu'une valeur est involontairement convertie entre heure locale et UTC.
  • Décalage d'un jour : une valeur de type date seule (comme "2025-12-23") apparaît comme le jour précédent/suivant selon le fuseau horaire.
  • Mauvais fuseau horaire : les heures semblent correctes, mais le décalage (par ex. +02:00) n'est pas celui attendu.
  • Formatage incohérent : « ça marche dans Chrome » mais diffère dans Safari, ou le serveur et le navigateur ne sont pas d'accord sur la manière d'analyser une chaîne.

Pourquoi cela arrive : « heure » peut signifier plusieurs choses

Une source majeure de problèmes est que le mot heure peut désigner des concepts différents :

  • Un instant : un moment précis dans le monde entier (ex. 2025-12-23T10:00:00Z). C'est généralement ce qu'on veut pour les logs, les événements et le stockage d'API.
  • Une date calendaire : un jour sur le calendrier sans fuseau horaire (ex. un anniversaire, une date de facture). Le traiter comme un instant peut le faire basculer sur un autre jour.
  • Heure « murale » : « 9:00 à Berlin », qui dépend des règles de fuseau horaire et des changements d'heure.

Le Date natif de JavaScript tente de couvrir tout cela, mais il représente principalement un instant dans le temps tout en vous poussant souvent vers un affichage local, ce qui facilite les conversions accidentelles.

Ce sur quoi cet article se concentre

Ce guide est volontairement pratique : comment obtenir des conversions prévisibles entre navigateurs et serveurs, comment choisir des formats plus sûrs (comme ISO 8601), et comment repérer les pièges classiques (secondes vs millisecondes, UTC vs local, et différences d'analyse). Le but n'est pas plus de théorie, mais moins de surprises « pourquoi ça a bougé ? ».

Types de données temporelles : timestamp, Date et chaîne

Les bugs de manipulation du temps en JavaScript commencent souvent par le mélange de représentations qui semblent interchangeables, mais ne le sont pas.

Les trois représentations que vous verrez le plus

1) Millisecondes epoch (nombre)

Un simple nombre comme 1735689600000 est typiquement les « millisecondes depuis 1970-01-01T00:00:00Z ». Il représente un instant sans format ni fuseau horaire attaché.

2) Objet Date (wrapper autour d'un instant)

Un Date stocke le même type d'instant qu'un timestamp. La partie confuse : quand vous affichez un Date, JavaScript le formate en utilisant les règles locales de l'environnement, à moins que vous ne demandiez autre chose.

3) Chaîne formatée (affichage humain)

Des chaînes comme "2025-01-01", "01/01/2025 10:00", ou "2025-01-01T00:00:00Z" ne sont pas toutes équivalentes. Certaines sont univoques (ISO 8601 avec Z), d'autres dépendent du locale, et certaines n'incluent pas de fuseau horaire du tout.

« Instant » vs « affichage humain »

  • Instant : « ce moment exact globalement » (à stocker en ms epoch ou en ISO UTC).
  • Affichage humain : « ce que l'utilisateur doit voir » (dépend du locale et du fuseau horaire).

Le même instant peut s'afficher différemment selon le fuseau horaire :

const instant = new Date("2025-01-01T00:00:00Z");

instant.toLocaleString("en-US", { timeZone: "UTC" });
// "1/1/2025, 12:00:00 AM"

instant.toLocaleString("en-US", { timeZone: "America/Los_Angeles" });
// "12/31/2024, 4:00:00 PM" (jour précédent)

Choisissez une « source de vérité »

Choisissez une représentation interne unique (fréquemment millisecondes epoch ou ISO 8601 UTC) et respectez-la dans toute l'application et les API. Convertissez vers/depuis Date et les chaînes formatées uniquement aux frontières : parsing des entrées et affichage UI.

Timestamps : secondes vs millisecondes (facile à confondre)

Un « timestamp » signifie généralement le temps epoch (aussi appelé Unix time) : le nombre d'unités écoulées depuis 1970-01-01 00:00:00 UTC. Le piège : différents systèmes utilisent des unités différentes.

Le Date de JavaScript est la source de la plupart des confusions parce qu'il utilise les millisecondes. De nombreuses API, bases de données et logs utilisent les secondes.

Règle simple

  • Unix timestamp (secondes) : 1704067200
  • Timestamp JavaScript (millisecondes) : 1704067200000

Même instant, mais la version en millisecondes a trois chiffres en plus.

Conversions sûres (secondes ↔ millisecondes)

Utilisez des multiplications/divisions explicites pour que l'unité soit évidente :

// seconds -> Date
const seconds = 1704067200;
const d1 = new Date(seconds * 1000);

// milliseconds -> Date
const ms = 1704067200000;
const d2 = new Date(ms);

// Date -> seconds
const secondsOut = Math.floor(d2.getTime() / 1000);

// Date -> milliseconds
const msOut = d2.getTime();

Le bug classique : passer des secondes à Date()

Cela paraît raisonnable, mais c'est faux lorsque ts est en secondes :

const ts = 1704067200;      // seconds
const d = new Date(ts);     // WRONG: treated as milliseconds

Le résultat sera une date en 1970, car 1,704,067,200 millisecondes ne représentent qu'environ 19 jours après l'époque.

Vérifications rapides pour valider

Quand vous n'êtes pas sûr de l'unité, ajoutez des garde-fous rapides :

function asDateFromUnknownEpoch(x) {
  // heuristic grossier : les secondes ~1e9-1e10, les millisecondes ~1e12-1e13
  if (x < 1e11) return new Date(x * 1000); // assume seconds
  return new Date(x);                      // assume milliseconds
}

const input = Number(valueFromApi);
console.log({ input, digits: String(Math.trunc(input)).length });
console.log('as ISO:', asDateFromUnknownEpoch(input).toISOString());

Si le nombre de "chiffres" est ~10, c'est probablement des secondes. Si c'est ~13, c'est probablement des millisecondes. Imprimez aussi toISOString() pendant le débogage : c'est sans ambiguïté et vous repèrez tout de suite les erreurs d'unité.

Heure locale vs UTC : pourquoi votre sortie bouge

Le Date de JavaScript peut être déroutant car il stocke un instant unique, mais peut présenter cet instant dans différents fuseaux horaires.

En interne, un Date est essentiellement « millisecondes depuis l'époque Unix (1970-01-01T00:00:00Z) ». Ce nombre représente un moment en UTC. Le "décalage" apparaît lorsque vous demandez à JavaScript de formater ce moment en heure locale (selon les paramètres de l'ordinateur/serveur) versus UTC.

Getters locaux vs getters UTC

Beaucoup d'API Date ont des variantes locales et UTC. Elles renvoient des valeurs différentes pour le même instant :

const d = new Date('2025-01-01T00:30:00Z');

d.getHours();      // heure en *heure locale*
d.getUTCHours();   // heure en UTC

d.toString();      // chaîne en heure locale
d.toISOString();   // UTC (termine toujours par Z)

Si votre machine est à New York (UTC-5), ce temps UTC peut apparaître comme « 19:30 » la veille en local. Sur un serveur réglé en UTC, il apparaîtra comme « 00:30 ». Même instant, affichage différent.

Pourquoi les logs semblent « faux »

Les logs utilisent souvent Date#toString() ou interpolent un Date de façon implicite, ce qui utilise le fuseau horaire local de l'environnement. Cela signifie que le même code peut afficher des timestamps différents sur votre portable, en CI et en production.

Conseils pratiques

Stockez et transmettez le temps en UTC (ex. millisecondes epoch ou ISO 8601 avec Z). Convertissez en heure locale de l'utilisateur uniquement pour l'affichage :

  • Pour les APIs : préférez toISOString() ou envoyez des millisecondes epoch
  • Pour l'UI : formatez dans le fuseau horaire de l'utilisateur avec Intl.DateTimeFormat

Si vous développez rapidement (par exemple avec un workflow type vibe-coding dans Koder.ai), il est utile d'intégrer cela tôt dans vos contrats d'API : nommez clairement les champs (createdAtMs, createdAtIso) et gardez le serveur (Go + PostgreSQL) et le client (React) cohérents sur ce que représente chaque champ.

Chaînes ISO 8601 : le format le plus sûr pour les APIs

Si vous devez envoyer des dates/heures entre un navigateur, un serveur et une base de données, les chaînes ISO 8601 sont le choix le plus sûr par défaut. Elles sont explicites, largement supportées et portent (surtout) l'information de fuseau horaire.

Utilisez UTC explicite ou un décalage explicite

Deux bons formats d'échange :

  • Heure UTC (recommandé si le fuseau local n'importe pas) : 2025-03-04T12:30:00Z
  • Heure locale avec un offset (recommandé quand l'heure locale importe) : 2025-03-04T12:30:00+02:00

Que signifie "Z" ?

Z signifie Zulu time, un autre nom pour UTC. Donc 2025-03-04T12:30:00Z est « 12:30 en UTC ».

Quand les offsets comme +02:00 sont importants ?

Les offsets sont cruciaux quand un événement est lié à un contexte de fuseau local (rendez-vous, réservations, heures d'ouverture). 2025-03-04T12:30:00+02:00 décrit un instant qui est deux heures en avance sur UTC, et ce n'est pas le même instant que 2025-03-04T12:30:00Z.

Évitez les chaînes ambiguës

Des chaînes comme 03/04/2025 sont un piège : est-ce le 4 mars ou le 3 avril ? Différents utilisateurs et environnements l'interprètent différemment. Préférez 2025-03-04 (date ISO) ou un datetime ISO complet.

Round-trip en sécurité (chaîne → Date → chaîne)

const iso = "2025-03-04T12:30:00Z";
const d = new Date(iso);
const back = d.toISOString();

console.log(iso);  // 2025-03-04T12:30:00Z
console.log(back); // 2025-03-04T12:30:00.000Z

Ce comportement de "round-trip" est exactement ce qu'on veut pour les APIs : cohérent, prévisible et conscient du fuseau horaire.

Pièges du parsing : Date.parse et différences entre navigateurs

Créez une API sûre pour la gestion du temps
Générez des endpoints React + Go avec des champs createdAtMs clairs et des payloads au format ISO 8601.

Date.parse() semble pratique : on lui passe une chaîne et on obtient un timestamp. Le problème, c'est que pour tout ce qui n'est pas clairement ISO 8601, l'analyse peut dépendre d'heuristiques du navigateur. Ces heuristiques ont varié entre moteurs et versions, ce qui signifie qu'une même entrée peut être analysée différemment (ou pas du tout) selon l'endroit où votre code s'exécute.

Pourquoi Date.parse() peut varier

JavaScript ne standardise l'analyse de façon fiable que pour les chaînes de type ISO 8601 (et encore, des détails comme le fuseau horaire importent). Pour des formats « conviviaux » — comme "03/04/2025", "March 4, 2025" ou "2025-3-4" — les navigateurs peuvent interpréter :

  • Mois/jour vs jour/mois selon des hypothèses locales
  • L'absence de fuseau horaire comme heure locale dans un moteur, mais rejetée dans un autre
  • Des chaînes légèrement malformées comme « assez proches »… jusqu'à ce que ce ne soit plus le cas

Si vous ne pouvez pas prédire la forme exacte de la chaîne, vous ne pouvez pas prédire le résultat.

Le cas surprenant : YYYY-MM-DD

Un piège courant est la forme date simple "YYYY-MM-DD" (par ex. "2025-01-15"). Beaucoup de développeurs s'attendent à ce qu'elle soit interprétée comme minuit local. En pratique, certains environnements traitent cette forme comme minuit UTC.

Cette différence compte : minuit UTC converti en heure locale peut devenir le jour précédent dans les zones à décalage négatif (ex. Amériques) ou décaler l'heure de façon inattendue. C'est une manière courante d'obtenir des bugs « pourquoi ma date est décalée d'un jour ? ».

Checklist de parsing : saisie utilisateur vs saisie serveur

Pour les entrées serveur/API :

  • Préférez l'ISO 8601 complet avec un fuseau horaire explicite, ex. 2025-01-15T13:45:00Z ou 2025-01-15T13:45:00+02:00.
  • Traitez les valeurs date-seules comme données, pas comme un instant. Si c'est un anniversaire ou une date d'échéance, conservez-la sous forme de chaîne ("YYYY-MM-DD") et n'utilisez pas Date sauf si vous définissez aussi le fuseau voulu.

Pour la saisie utilisateur :

  • N'acceptez pas des formats ambigus comme 03/04/2025 à moins que votre UI n'impose le sens.
  • Préférez des entrées contrôlées (date pickers) qui produisent un format connu.
  • Si vous devez analyser du texte libre, définissez et appliquez les formats acceptés dès le départ.

Utilisez des règles explicites (pas des heuristiques)

Au lieu de compter sur Date.parse() qui « devine », choisissez l'une de ces approches :

  • N'acceptez que l'ISO 8601 côté serveur ; rejetez le reste.
  • Parsez manuellement des formats connus (séparez la chaîne et utilisez new Date(year, monthIndex, day) pour les dates locales).
  • Stockez et transmettez des timestamps (millisecondes epoch) pour des instants précis, et formatez pour l'affichage plus tard.

Quand les données temporelles sont critiques, « ça parse sur ma machine » ne suffit pas — rendez vos règles d'analyse explicites et cohérentes.

Formatage pour les humains avec Intl.DateTimeFormat

Si votre objectif est « afficher une date/heure comme les gens s'attendent », le meilleur outil en JavaScript est Intl.DateTimeFormat. Il utilise les règles locales de l'utilisateur (ordre, séparateurs, noms de mois) et évite l'approche fragile d'assembler des chaînes à la main comme month + '/' + day.

Pourquoi c'est mieux que d'assembler à la main

Le formatage manuel code souvent en dur un style US, oublie des zéros non significatifs, ou produit des résultats déroutants 24/12 heures. Intl.DateTimeFormat rend aussi explicite dans quel fuseau horaire vous affichez — critique quand les données sont stockées en UTC mais l'UI doit refléter l'heure locale de l'utilisateur.

Options courantes que vous utiliserez réellement

Pour « juste formater joliment », dateStyle et timeStyle sont les plus simples :

const d = new Date('2025-01-05T16:30:00Z');

// Locale de l'utilisateur + fuseau horaire local de l'utilisateur
console.log(new Intl.DateTimeFormat(undefined, {
  dateStyle: 'medium',
  timeStyle: 'short'
}).format(d));

// Forcer un fuseau horaire spécifique (utile pour les heures d'événements)
console.log(new Intl.DateTimeFormat('en-GB', {
  dateStyle: 'full',
  timeStyle: 'short',
  timeZone: 'UTC'
}).format(d));

Si vous avez besoin d'un cycle horaire cohérent (par ex. un réglage), utilisez hour12 :

console.log(new Intl.DateTimeFormat('en-US', {
  hour: 'numeric',
  minute: '2-digit',
  hour12: true
}).format(d));

Un pattern UI pratique

Choisissez une fonction de formatage par « type » de timestamp dans votre UI (heure d'un message, entrée de log, début d'événement) et gardez la décision timeZone intentionnelle :

  • Utilisez l'heure locale pour « quand c'est arrivé pour moi ».
  • Utilisez un fuseau fixe (souvent UTC) pour les logs d'audit, événements serveur, ou coordination inter-équipes.

Cela vous donne un affichage cohérent et adapté au locale sans maintenir un ensemble fragile de chaînes de format personnalisées.

Heure d'été (DST) : le bug caché « moins une heure »

Obtenez des récompenses en partageant vos builds
Partagez vos créations et gagnez des crédits via le contenu et les parrainages.

L'heure d'été (DST) correspond aux moments où un fuseau horaire change son offset UTC (généralement d'une heure) à des dates spécifiques. La partie délicate : DST ne modifie pas seulement le décalage — elle modifie l'existence de certaines heures locales.

Heures locales manquantes et dupliquées

Quand les horloges avancent, une plage d'heures locales n'existe pas. Par exemple, dans de nombreuses régions, l'horloge saute de 01:59 à 03:00, donc 02:30 heure locale est "manquante".

Quand les horloges reculent, une plage d'heures locales se produit deux fois. Par exemple, 01:30 peut se produire une fois avant le changement et une autre après, ce qui signifie qu'une même heure locale peut désigner deux instants différents.

Ajouter 24 heures vs « même heure locale demain »

Ce n'est pas équivalent autour des frontières DST :

  • Ajouter 24 heures : "exactement 24 * 60 * 60 secondes plus tard"
  • Demain à la même heure locale : "demain à 9:00 dans ce fuseau"

Si DST commence ce soir, "demain à 9:00" peut être à 23 heures d'écart. Si DST finit, cela peut être 25 heures d'écart.

// Scénario : programmer « même heure locale demain »
const d = new Date(2025, 2, 8, 9, 0); // 8 mars, 9:00 heure locale

const plus24h = new Date(d.getTime() + 24 * 60 * 60 * 1000);
const nextDaySameLocal = new Date(d);
nextDaySameLocal.setDate(d.getDate() + 1);

// Autour de DST, plus24h et nextDaySameLocal peuvent différer d'une heure.

Pourquoi setHours peut vous surprendre

Si vous faites quelque chose comme date.setHours(2, 30, 0, 0) un jour de « spring forward », JavaScript peut normaliser en une autre heure valide (souvent 03:30), parce que 02:30 n'existe pas en heure locale.

Approches plus sûres

  • Faites les calculs en UTC pour les durées écoulées : utilisez les millisecondes epoch et les méthodes UTC.
  • Pour la planification locale, soyez explicite sur l'intention : "demain à 9:00 locale" doit utiliser des opérations calendaires (setDate) plutôt que d'ajouter des millisecondes.
  • Lors de l'échange d'heures via APIs, préférez ISO 8601 avec offset ou Z pour que l'instant soit sans ambiguïté.

Durées vs Dates : n'utilisez pas Date pour un minuteur

Une source courante de bugs est d'utiliser Date pour représenter quelque chose qui n'est pas un instant calendaire.

Un timestamp répond à « quand cela s'est produit ? » (un instant précis comme 2025-12-23T10:00:00Z). Une durée répond à « combien de temps ? » (comme « 3 minutes 12 secondes »). Ce sont des concepts différents, et les mélanger mène à des calculs confus et à des effets inattendus liés aux fuseaux/DST.

Pourquoi Date est le mauvais outil pour les durées

Date représente toujours un point sur la timeline relatif à une époque. Si vous stockez « 90 secondes » comme un Date, vous stockez en réalité "1970-01-01 plus 90 secondes" dans un fuseau particulier. Le formatage peut alors afficher 01:01:30, être décalé d'une heure, ou afficher une date que vous ne vouliez pas.

Pour les durées, préférez des nombres :

  • Stockez les durées en secondes ou millisecondes (choisissez une unité et tenez-vous-y).
  • Faites l'arithmétique avec des nombres.
  • Convertissez en chaîne d'affichage seulement à la fin.

Conversion secondes → HH:mm:ss

Voici un formateur simple qui fonctionne pour des compte-à-rebours et longueurs média :

function formatHMS(totalSeconds) {
  const s = Math.max(0, Math.floor(totalSeconds));
  const hh = String(Math.floor(s / 3600)).padStart(2, "0");
  const mm = String(Math.floor((s % 3600) / 60)).padStart(2, "0");
  const ss = String(s % 60).padStart(2, "0");
  return `${hh}:${mm}:${ss}`;
}

formatHMS(75);    // "00:01:15" (compte à rebours)
formatHMS(5423);  // "01:30:23" (durée média)

Si vous convertissez depuis des minutes, multipliez d'abord (minutes * 60) et gardez la valeur numérique jusqu'au rendu.

Comparaisons, tri et plages sans surprises

Quand vous comparez des temps en JavaScript, l'approche la plus sûre est de comparer des nombres, pas des textes formatés. Un objet Date est essentiellement un wrapper autour d'un timestamp numérique (millisecondes epoch), donc vous voulez que les comparaisons se fassent comme "nombre vs nombre".

Comparaisons sûres (les timestamps gagnent)

Utilisez getTime() (ou Date.valueOf(), qui renvoie le même nombre) pour comparer de manière fiable :

const a = new Date('2025-01-10T12:00:00Z');
const b = new Date('2025-01-10T12:00:01Z');

if (a.getTime() < b.getTime()) {
  // a est avant
}

// Marche aussi :
if (+a < +b) {
  // l'unaire + appelle valueOf()
}

Évitez de comparer des chaînes formatées comme "1/10/2025, 12:00 PM" — elles dépendent du locale et ne trieront pas correctement. L'exception principale est les chaînes ISO 8601 dans le même format et fuseau (ex. toutes en ...Z), qui sont triables lexicographiquement.

Tri et filtrage par plage

Le tri par temps est simple si vous triez par millisecondes epoch :

items.sort((x, y) => new Date(x.createdAt).getTime() - new Date(y.createdAt).getTime());

Le filtrage d'items dans une plage suit la même idée :

const start = new Date('2025-01-01T00:00:00Z').getTime();
const end   = new Date('2025-02-01T00:00:00Z').getTime();

const inRange = items.filter(i => {
  const t = new Date(i.createdAt).getTime();
  return t >= start && t < end;
});

« Début/fin de journée » (local vs UTC)

"Début de journée" dépend de si vous entendez heure locale ou UTC :

// Début/fin de journée locale
const d = new Date(2025, 0, 10); // 10 janv en heure locale
const localStart = new Date(d.getFullYear(), d.getMonth(), d.getDate(), 0, 0, 0, 0);
const localEnd   = new Date(d.getFullYear(), d.getMonth(), d.getDate(), 23, 59, 59, 999);

// Début/fin de journée UTC
const utcStart = new Date(Date.UTC(2025, 0, 10, 0, 0, 0, 0));
const utcEnd   = new Date(Date.UTC(2025, 0, 10, 23, 59, 59, 999));

Choisissez une définition tôt et tenez-vous-y pour toutes vos comparaisons et logique de plages.

Checklist de débogage : comment diagnostiquer un bug de conversion temporelle

Planifiez votre contrat de données temporelles
Utilisez Planning Mode pour définir les contrats temporels avant la génération de code.

Les bugs temporels semblent aléatoires jusqu'à ce que vous déterminiez ce que vous avez (timestamp ? chaîne ? Date ?) et le décalage est introduit (parsing, conversion de fuseau, formatage).

1) Capturez les « trois vues » du même instant

Commencez par logger la même valeur de trois façons différentes. Cela révèle rapidement si le problème vient des secondes vs millisecondes, du local vs UTC, ou du parsing.

console.log('raw input:', input);

const d = new Date(input);
console.log('toISOString (UTC):', d.toISOString());
console.log('toString (local):', d.toString());
console.log('timezone offset (min):', d.getTimezoneOffset());

Que rechercher :

  • Si toISOString() est complètement à côté (ex. année 1970 ou très futur), suspectez secondes vs millisecondes.
  • Si toISOString() semble correct mais toString() est "décalé", vous voyez un problème d'affichage en fuseau local.
  • Si getTimezoneOffset() change selon la date, vous traversez une heure d'été.

2) Vérifiez l'environnement : fuseau horaire et locale

Beaucoup de rapports « ça marche sur ma machine » tiennent simplement aux valeurs par défaut de l'environnement.

  • Navigateur : vérifiez les paramètres OS du fuseau horaire et la langue du navigateur. Puis loggez :
console.log(Intl.DateTimeFormat().resolvedOptions());
  • Node.js / serveur : confirmez le fuseau horaire du process :
console.log('TZ:', process.env.TZ);
console.log(Intl.DateTimeFormat().resolvedOptions().timeZone);

Si votre serveur tourne en UTC mais votre portable en zone locale, l'affichage formaté diffèrera à moins de spécifier explicitement timeZone.

3) Ajoutez des tests là où le temps casse le plus souvent

Créez des tests unitaires autour des frontières DST et des heures critiques :

  • Une heure avant et après le basculement DST dans la zone concernée
  • Fin de mois/année, et les passages 23:3000:30
  • Plusieurs fuseaux horaires si votre produit les supporte

Si vous itérez vite, envisagez d'intégrer ces tests dans votre scaffolding. Par exemple, quand vous générez une appli React + Go avec Koder.ai, ajoutez une petite suite de « time contract » en amont (exemples de payloads API + assertions parsing/formatting) pour attraper les régressions avant déploiement.

Checklist rapide avant publication

  • Les entrées ont un contrat clair : millisecondes epoch ou ISO 8601 avec offset.
  • Pas de chaînes ambiguës comme "2025-03-02 10:00".
  • Le formatage spécifie toujours locale et (si nécessaire) timeZone.
  • Les tests couvrent les frontières DST pour vos régions cibles.

Patterns recommandés pour une gestion fiable du temps

Une gestion fiable du temps en JavaScript consiste surtout à choisir une « source de vérité » et à être cohérent du stockage à l'affichage.

Ensemble simple de bonnes pratiques

Stockez et calculez en UTC. Traitez l'heure locale comme un détail de présentation.

Transmettez les dates entre systèmes comme des chaînes ISO 8601 avec un offset explicite (de préférence Z). Si vous devez envoyer des epochs numériques, documentez l'unité et restez cohérent (les millisecondes sont le défaut courant en JS).

Formatez pour les humains avec Intl.DateTimeFormat (ou toLocaleString), et passez un timeZone explicite quand vous avez besoin d'un rendu déterministe (par ex. toujours afficher en UTC ou dans une région d'affaires spécifique).

Guide de décision : DB vs API vs UI

  • Base de données : stockez un instant en UTC (millisecondes epoch ou type datetime UTC). Évitez les datetimes locales sauf si votre domaine stocke vraiment des heures murales (comme « le magasin ouvre à 09:00 »).
  • API : préférez ISO 8601 avec Z (ex. 2025-12-23T10:15:00Z). Si vous utilisez des epochs, nommez le champ comme createdAtMs pour préciser l'unité.
  • UI : prenez l'instant UTC stocké et formatez-le pour le locale de l'utilisateur. Pour les interfaces de planification, indiquez clairement le fuseau horaire et faites des conversions explicites.

Quand une librairie vaut le coup

Envisagez une bibliothèque dédiée si vous avez besoin d'événements récurrents, de règles complexes de fuseau horaire, d'arithmétique sûre autour de DST ("même heure locale demain"), ou beaucoup de parsing d'entrées incohérentes. La valeur réside dans des APIs plus claires et moins de bugs aux bords.

Si vous voulez aller plus loin, consultez d'autres guides sur le temps à /blog. Si vous évaluez des outils ou options de support, voyez /pricing.

FAQ

Quel format utiliser pour les horodatages en JavaScript ?

Utilisez des millisecondes depuis l’époque Unix ou une chaîne ISO 8601 en UTC comme format interne. Convertissez dans un format local uniquement lorsque vous affichez la valeur à une personne.

Pourquoi mon horodatage Unix devient-il une date en 1970 ?

JavaScript Date attend des millisecondes. Multipliez un horodatage Unix en secondes par 1000 avant de le passer à new Date().

Pourquoi la même date affiche-t-elle des heures différentes sur différents ordinateurs ?

Un Date stocke un instant précis, mais JavaScript l’affiche souvent dans le fuseau horaire local de l’ordinateur. Comparez toISOString() et toString() pour voir si les données ont changé ou si seul l’affichage a changé.

Comment empêcher une date de se décaler d’un jour ?

Conservez une valeur ne contenant que la date, comme une date d’anniversaire ou de facture, au format YYYY-MM-DD. Ne la transformez pas en Date tant que vous n’avez pas défini le fuseau horaire voulu.

Quel format de date est le plus sûr pour une API ?

Envoyez une valeur ISO 8601 complète avec Z pour l’UTC, comme 2025-03-04T12:30:00Z, ou incluez un décalage explicite. Évitez les chaînes comme 03/04/2025, car les personnes et les navigateurs peuvent les interpréter différemment.

Comment formater les dates pour les utilisateurs ?

Utilisez Intl.DateTimeFormat et indiquez un timeZone lorsque l’écran doit utiliser un fuseau fixe. Il formate les dates selon les paramètres régionaux de l’utilisateur, sans construire manuellement les chaînes.

Dois-je utiliser Date.parse pour les dates saisies par les utilisateurs ?

Ne vous y fiez pas pour les chaînes informelles ou ambiguës. Acceptez un format ISO connu provenant des API, ou analysez les saisies utilisateur contrôlées avec des règles que vous définissez vous-même.

Pourquoi éviter d’utiliser Date pour un compte à rebours ou une durée ?

Un Date désigne un moment du calendrier, tandis qu’une durée n’est qu’une quantité de temps. Stockez les durées en secondes ou en millisecondes, puis formatez le nombre lors de l’affichage.

Comment l’heure d’été affecte-t-elle les dates JavaScript ?

Utilisez les millisecondes depuis l’époque Unix pour les calculs de temps écoulé. Pour des horaires comme « demain à 9 h 00 » dans un fuseau nommé, utilisez des opérations basées sur le calendrier et testez les dates de transition vers l’heure d’été.

Quelle est la façon la plus rapide de déboguer un problème d’heure en JavaScript ?

Journalisez l’entrée brute, toISOString(), toString() et getTimezoneOffset(). Une valeur ISO erronée indique souvent un problème d’analyse ou d’unité, tandis qu’une chaîne locale différente indique généralement une différence d’affichage liée au fuseau horaire.

Related posts