Back

Afficher l'heure de manière lisible dans le navigateur

Afficher l'heure de manière lisible dans le navigateur

Votre serveur stocke les horodatages en UTC. Vos utilisateurs vivent dans des dizaines de fuseaux horaires. L’écart entre ces deux réalités—chaînes ISO brutes versus « il y a 2 heures »—détermine si votre interface semble native ou étrangère.

Les navigateurs modernes gèrent désormais l’affichage d’heures lisibles en JavaScript sans bibliothèques tierces. Cet article couvre les API natives à privilégier : Intl.DateTimeFormat, Intl.RelativeTimeFormat, Intl.DurationFormat, et l’API Temporal pour la logique tenant compte des fuseaux horaires.

Points clés à retenir

  • Utilisez Intl.DateTimeFormat pour les horodatages absolus adaptés aux paramètres régionaux, en passant directement les identifiants de fuseau horaire IANA pour éviter les calculs manuels de décalage.
  • Utilisez Intl.RelativeTimeFormat avec une petite fonction utilitaire pour produire des expressions naturelles comme « hier » ou « il y a 3 heures ».
  • Utilisez Intl.DurationFormat pour le temps écoulé et les comptes à rebours, mais vérifiez la compatibilité des navigateurs car la disponibilité de base n’est arrivée qu’en 2025.
  • L’API Temporal remplace l’objet Date sujet aux erreurs par des types explicites et immuables—adoptez-la pour les nouveaux projets tout en vous appuyant sur les formateurs Intl pour les bases de code existantes.

Horodatages absolus avec Intl.DateTimeFormat

Lorsque les utilisateurs ont besoin de dates et heures exactes, Intl.DateTimeFormat gère automatiquement la localisation. Elle respecte les paramètres régionaux de l’utilisateur et formate les dates selon les conventions régionales.

const date = new Date('2026-03-15T14:30:00Z')

const formatter = new Intl.DateTimeFormat('en-US', {
  dateStyle: 'medium',
  timeStyle: 'short',
  timeZone: 'America/New_York'
})

console.log(formatter.format(date)) // "Mar 15, 2026, 10:30 AM"

L’API accepte directement les identifiants de fuseau horaire IANA, éliminant les calculs manuels de décalage. Pour un formatage adapté aux paramètres locaux de l’utilisateur, détectez automatiquement le fuseau horaire :

const userTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone

Cela retourne des valeurs comme "Europe/London" ou "Asia/Tokyo", que vous pouvez passer directement aux formateurs.

Temps relatif avec Intl.RelativeTimeFormat

Les fils d’actualité, notifications et journaux d’activité bénéficient d’horodatages relatifs. Intl.RelativeTimeFormat produit des expressions comme « il y a 3 jours » ou « dans 2 heures » avec une localisation appropriée.

const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' })

rtf.format(-1, 'day')    // "yesterday"
rtf.format(-3, 'hour')   // "3 hours ago"
rtf.format(2, 'week')    // "in 2 weeks"

L’option numeric: 'auto' produit un langage naturel (« yesterday ») au lieu de nombres littéraux (« 1 day ago ») lorsque c’est approprié.

Vous devez calculer la différence vous-même—l’API formate des valeurs, pas des dates. Une fonction utilitaire simple suffit :

function getRelativeTime(date) {
  const now = Date.now()
  const diffInSeconds = Math.round((date - now) / 1000)
  const units = [
    { unit: 'year', seconds: 31536000 },
    { unit: 'month', seconds: 2592000 },
    { unit: 'day', seconds: 86400 },
    { unit: 'hour', seconds: 3600 },
    { unit: 'minute', seconds: 60 },
    { unit: 'second', seconds: 1 }
  ]

  for (const { unit, seconds } of units) {
    if (Math.abs(diffInSeconds) >= seconds) {
      const value = Math.round(diffInSeconds / seconds)
      return new Intl.RelativeTimeFormat('en', { numeric: 'auto' })
        .format(value, unit)
    }
  }
  return 'just now'
}

Les valeurs de mois et d’année ci-dessus utilisent des approximations en secondes fixes. Pour des différences calendaires précises tenant compte des longueurs de mois variables ou des années bissextiles, utilisez Temporal ou une bibliothèque de dates dédiée plutôt que des constantes de secondes fixes.

Notez que Math.round peut occasionnellement pousser une valeur vers l’unité suivante (par exemple, 89 secondes arrondies à 1 lorsque divisées par 60, produisant « 1 minute ago » au lieu de « 89 seconds ago »). Si vous avez besoin de limites plus strictes, utilisez Math.trunc à la place.

Formatage de durée avec Intl.DurationFormat

Pour le temps écoulé, les comptes à rebours ou les durées de vidéos, Intl.DurationFormat fournit une sortie cohérente dans toutes les langues :

const duration = { hours: 2, minutes: 45, seconds: 30 }

const df = new Intl.DurationFormat('en', { style: 'long' })
console.log(df.format(duration)) // "2 hours, 45 minutes, 30 seconds"

const dfShort = new Intl.DurationFormat('en', { style: 'digital' })
console.log(dfShort.format(duration)) // "2:45:30"

Cette API a atteint une prise en charge de base multi-moteurs en 2025 et est disponible dans les navigateurs modernes, bien que vous devriez toujours confirmer la compatibilité avec votre matrice de support spécifique.

L’API Temporal pour une gestion plus sûre des dates

L’API Temporal résout les problèmes de longue date de l’objet Date de JavaScript—mutabilité, confusion des fuseaux horaires et incohérences d’analyse. Temporal est pris en charge dans les versions modernes de Chromium et Firefox depuis 2026, mais la détection de fonctionnalité reste essentielle car la prise en charge n’est pas encore universelle dans tous les navigateurs.

if (typeof Temporal !== 'undefined') {
  const now = Temporal.Now.zonedDateTimeISO('America/Los_Angeles')
  console.log(now.toString())
}

Temporal fournit des types distincts pour différents concepts : Temporal.PlainDate pour les dates calendaires, Temporal.PlainTime pour l’heure murale, et Temporal.ZonedDateTime pour les moments tenant compte du fuseau horaire. Cette explicité prévient les bugs qui affligent le code basé sur Date.

Pour les nouveaux projets, Temporal offre la base la plus propre. Pour les bases de code existantes, les formateurs Intl fonctionnent parfaitement avec les objets Date hérités.

Recommandations pratiques

Stockez les horodatages sous forme de chaînes ISO 8601 en UTC. Formatez-les côté client en utilisant les API Intl. Évitez d’analyser des chaînes de dates non-ISO—elles se comportent de manière incohérente d’un navigateur à l’autre.

Réutilisez les instances de formateurs lors du formatage de plusieurs horodatages. Créer un formateur une fois et appeler format() de manière répétée est significativement plus rapide que d’en recréer un à chaque appel.

Utilisez du HTML sémantique pour l’accessibilité :

<time datetime="2026-03-15T14:30:00Z">March 15, 2026</time>

Conclusion

La plateforme native gère désormais ce qui nécessitait autrefois Moment.js ou des bibliothèques similaires. Intl.DateTimeFormat couvre les horodatages absolus, Intl.RelativeTimeFormat couvre les expressions relatives, Intl.DurationFormat couvre le temps écoulé, et l’API Temporal fournit une base solide pour la logique de dates tenant compte des fuseaux horaires. Pour afficher l’heure de manière lisible dans le navigateur, ces outils intégrés sont tout ce dont vous avez besoin.

FAQ

Non. L'API ne fait que formater une valeur numérique et une unité en une chaîne localisée. Vous devez calculer vous-même la différence entre deux dates et choisir l'unité appropriée avant de les passer à la méthode format. La fonction utilitaire présentée dans cet article est un modèle courant pour ce calcul.

Temporal est disponible dans les versions modernes de Chromium et Firefox depuis 2026, mais n'est pas encore universellement pris en charge dans tous les navigateurs. Utilisez toujours la détection de fonctionnalité avant d'appeler les méthodes Temporal, et envisagez un polyfill si vous avez besoin d'une large compatibilité. Pour le formatage seul, les API Intl ont déjà une large prise en charge et fonctionnent bien avec l'objet Date hérité.

Construire un formateur Intl implique de résoudre les données de paramètres régionaux, les règles de fuseau horaire et les options de formatage, ce qui a un coût mesurable. Créer une instance et appeler sa méthode format de manière répétée est significativement plus rapide que de reconstruire le formateur à chaque invocation, en particulier lors du rendu de longues listes d'horodatages.

Par défaut, oui. Si vous omettez l'option timeZone, le formateur utilise le fuseau horaire de l'environnement d'exécution, qui dans un navigateur correspond au paramètre système de l'utilisateur. Vous pouvez récupérer cette valeur explicitement via Intl.DateTimeFormat().resolvedOptions().timeZone et la passer à d'autres formateurs ou l'envoyer à votre serveur.

Complete picture for complete understanding

Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.

Check our GitHub repo and join the thousands of developers in our community.

OpenReplay