API Intl.DurationFormat

Formatez les durées temporelles en JavaScript avec localisation automatique

Introduction

Lorsque vous affichez la durée d'un élément, vous devez formater les valeurs de durée pour les utilisateurs. Un lecteur vidéo affiche la durée de lecture, une réservation de vol indique le temps de trajet, une application de fitness montre la durée d'entraînement. Sans localisation, vous pourriez écrire du code comme celui-ci :

const hours = 1;
const minutes = 46;
const seconds = 40;
const duration = `${hours}h ${minutes}m ${seconds}s`;

Cela produit "1h 46m 40s" pour tous les utilisateurs, quelle que soit leur langue. Les utilisateurs français voient "1h 46m 40s" alors qu'ils s'attendent à "1 h 46 min 40 s". Les utilisateurs allemands voient les mêmes abréviations en anglais. Les utilisateurs espagnols n'ont pas de conjonction "y" entre les unités.

L'API Intl.DurationFormat résout ce problème. Elle formate les durées selon la langue et les conventions culturelles de l'utilisateur sans bibliothèques externes ni construction manuelle de chaînes.

const duration = { hours: 1, minutes: 46, seconds: 40 };
new Intl.DurationFormat('fr-FR', { style: 'short' }).format(duration);
// "1 h, 46 min et 40 s"

Le formateur gère automatiquement les abréviations, les conjonctions, l'ordre des mots et l'espacement pour n'importe quelle locale.

Qu'est-ce que les durées

Une durée représente une période de temps, et non un point dans le temps. Les dates et heures marquent quand quelque chose se produit. Les durées mesurent combien de temps quelque chose prend.

Cette distinction est importante pour le formatage. Les dates impliquent des calendriers, des fuseaux horaires et des règles historiques. Les durées sont plus simples : elles mesurent le temps écoulé en unités standard sans contexte de calendrier.

L'API Intl.DurationFormat gère les durées. L'API Intl.DateTimeFormat gère les dates et les heures. Utilisez le bon outil pour chaque tâche.

Créer un formateur de durée

Le constructeur prend une locale et un objet d'options. La locale détermine la langue de sortie. Les options contrôlent le style de formatage et l'affichage des unités.

const formatter = new Intl.DurationFormat('en', { style: 'long' });

Appelez format() avec un objet de durée. L'objet contient des propriétés numériques pour les unités de temps. N'incluez que les unités que vous souhaitez afficher.

const duration = { hours: 2, minutes: 30 };
formatter.format(duration);
// "2 hours and 30 minutes"

L'API prend en charge ces unités de temps : years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds. Utilisez les unités qui correspondent à vos données.

Choisir un style de formatage

L'option style contrôle la densité de sortie. Quatre styles sont disponibles : long, short, narrow, et digital.

Le style long utilise des mots complets. Utilisez-le pour la prose et l'accessibilité.

const duration = { hours: 1, minutes: 46, seconds: 40 };
new Intl.DurationFormat('en', { style: 'long' }).format(duration);
// "1 hour, 46 minutes and 40 seconds"

Le style court utilise des abréviations courantes. Utilisez-le lorsque l'espace est limité mais que la lisibilité est importante.

new Intl.DurationFormat('en', { style: 'short' }).format(duration);
// "1 hr, 46 min and 40 sec"

Le style étroit utilise un minimum de caractères. Utilisez-le pour les affichages compacts comme les interfaces mobiles.

new Intl.DurationFormat('en', { style: 'narrow' }).format(duration);
// "1h 46m 40s"

Le style digital produit une sortie similaire à un minuteur avec des deux-points. Utilisez-le pour les lecteurs multimédias et les affichages de compte à rebours.

new Intl.DurationFormat('en', { style: 'digital' }).format(duration);
// "1:46:40"

Localisation à travers les langues

La même durée est formatée différemment dans chaque langue. L'API gère automatiquement toute la localisation.

const duration = { hours: 1, minutes: 46, seconds: 40 };

new Intl.DurationFormat('en', { style: 'long' }).format(duration);
// "1 hour, 46 minutes and 40 seconds"

new Intl.DurationFormat('fr', { style: 'long' }).format(duration);
// "1 heure, 46 minutes et 40 secondes"

new Intl.DurationFormat('de', { style: 'long' }).format(duration);
// "1 Stunde, 46 Minuten und 40 Sekunden"

new Intl.DurationFormat('es', { style: 'long' }).format(duration);
// "1 hora, 46 minutos y 40 segundos"

new Intl.DurationFormat('ja', { style: 'long' }).format(duration);
// "1時間46分40秒"

Remarquez comment chaque locale utilise différents mots, abréviations et conjonctions. Le français utilise "et", l'allemand utilise "und", l'espagnol utilise "y", le japonais n'utilise pas de conjonctions. L'API connaît ces règles.

Les styles court et étroit sont également correctement localisés.

new Intl.DurationFormat('fr', { style: 'short' }).format(duration);
// "1 h, 46 min et 40 s"

new Intl.DurationFormat('de', { style: 'narrow' }).format(duration);
// "1 Std. 46 Min. 40 Sek."

Créer des objets de durée à partir de calculs de temps

Les objets de durée sont des objets JavaScript simples avec des propriétés d'unités de temps. Créez-les à partir de n'importe quel calcul de temps.

Convertissez les millisecondes en unités de durée en divisant par les facteurs appropriés.

const milliseconds = 6400000; // 1 heure, 46 minutes, 40 secondes
const hours = Math.floor(milliseconds / 3600000);
const minutes = Math.floor((milliseconds % 3600000) / 60000);
const seconds = Math.floor((milliseconds % 60000) / 1000);

const duration = { hours, minutes, seconds };
new Intl.DurationFormat('en', { style: 'short' }).format(duration);
// "1 hr, 46 min and 40 sec"

Calculez la durée entre deux dates en soustrayant les timestamps.

const start = new Date('2025-01-01T10:00:00');
const end = new Date('2025-01-01T11:46:40');
const diffMs = end - start;

const hours = Math.floor(diffMs / 3600000);
const minutes = Math.floor((diffMs % 3600000) / 60000);
const seconds = Math.floor((diffMs % 60000) / 1000);

const duration = { hours, minutes, seconds };

Incluez uniquement les unités dont vous avez besoin. Omettez les valeurs nulles sauf si vous souhaitez les afficher.

const duration = { minutes: 5, seconds: 30 };
new Intl.DurationFormat('en', { style: 'long' }).format(duration);
// "5 minutes and 30 seconds"

Contrôler quelles unités apparaissent

Par défaut, le formateur affiche toutes les unités que vous fournissez dans l'objet de durée. Contrôlez l'affichage des unités avec l'objet d'options.

Spécifiez le style d'affichage pour chaque unité individuellement. Les options sont long, short, narrow, numeric et 2-digit.

const duration = { hours: 1, minutes: 5, seconds: 3 };

new Intl.DurationFormat('en', {
  hours: 'long',
  minutes: 'numeric',
  seconds: '2-digit'
}).format(duration);
// "1 hour, 5:03"

Le style numeric affiche le nombre sans étiquettes. Le style 2-digit ajoute des zéros de remplissage. Utilisez-les pour des affichages compacts mélangeant texte et nombres.

Masquez les unités en les omettant à la fois de l'objet de durée et des options.

const duration = { hours: 2, minutes: 30 };
new Intl.DurationFormat('en', { style: 'short' }).format(duration);
// "2 hr and 30 min"

Le style numérique nécessite que toutes les unités, de la plus grande à la plus petite, soient présentes ou explicitement configurées.

const duration = { minutes: 5, seconds: 30 };
new Intl.DurationFormat('en', { style: 'digital' }).format(duration);
// "5:30"

Formater les durées du lecteur vidéo

Les lecteurs vidéo affichent la durée dans les contrôles. Utilisez le style étroit ou numérique pour un affichage compact.

function formatVideoDuration(seconds) {
  const hours = Math.floor(seconds / 3600);
  const minutes = Math.floor((seconds % 3600) / 60);
  const secs = Math.floor(seconds % 60);

  const duration = hours > 0
    ? { hours, minutes, seconds: secs }
    : { minutes, seconds: secs };

  const locale = navigator.language;
  return new Intl.DurationFormat(locale, { style: 'digital' }).format(duration);
}

formatVideoDuration(6400); // "1:46:40"
formatVideoDuration(330);  // "5:30"

Cela gère à la fois les vidéos courtes et longues en incluant conditionnellement les heures.

Formater les temps de vol et de voyage

Les interfaces de réservation de voyages affichent la durée du trajet. Utilisez le style court pour une meilleure lisibilité dans un espace limité.

function formatFlightDuration(departureDate, arrivalDate, locale) {
  const diffMs = arrivalDate - departureDate;
  const hours = Math.floor(diffMs / 3600000);
  const minutes = Math.floor((diffMs % 3600000) / 60000);

  const duration = { hours, minutes };
  return new Intl.DurationFormat(locale, { style: 'short' }).format(duration);
}

const departure = new Date('2025-06-15T10:30:00');
const arrival = new Date('2025-06-15T18:45:00');

formatFlightDuration(departure, arrival, 'en');
// "8 hr and 15 min"

formatFlightDuration(departure, arrival, 'fr');
// "8 h et 15 min"

Formater les durées d'entraînement et d'activité

Les applications de fitness suivent la durée d'exercice. Utilisez le style long pour les résumés de session et le style étroit pour les vues en liste.

function formatWorkoutDuration(startTime, endTime, locale) {
  const diffMs = endTime - startTime;
  const hours = Math.floor(diffMs / 3600000);
  const minutes = Math.floor((diffMs % 3600000) / 60000);

  const duration = hours > 0
    ? { hours, minutes }
    : { minutes };

  return new Intl.DurationFormat(locale, { style: 'long' }).format(duration);
}

const workoutStart = new Date('2025-06-15T07:00:00');
const workoutEnd = new Date('2025-06-15T08:15:00');

formatWorkoutDuration(workoutStart, workoutEnd, 'en');
// "1 hour and 15 minutes"

Obtenir des parties formatées pour un affichage personnalisé

La méthode formatToParts() renvoie un tableau d'objets représentant chaque partie de la sortie formatée. Utilisez-la pour styliser des parties individuelles ou créer des mises en page personnalisées.

const duration = { hours: 1, minutes: 46, seconds: 40 };
const parts = new Intl.DurationFormat('en', { style: 'long' }).formatToParts(duration);

Chaque partie possède un type et une value. Les types incluent hour, minute, second, literal, et des étiquettes d'unité comme hourUnit, minuteUnit.

[
  { type: "integer", value: "1" },
  { type: "literal", value: " " },
  { type: "unit", value: "hour" },
  { type: "literal", value: ", " },
  { type: "integer", value: "46" },
  { type: "literal", value: " " },
  { type: "unit", value: "minutes" },
  { type: "literal", value: " and " },
  { type: "integer", value: "40" },
  { type: "literal", value: " " },
  { type: "unit", value: "seconds" }
]

Parcourez les parties pour appliquer un style personnalisé.

function StyledDuration({ duration }) {
  const parts = new Intl.DurationFormat('en', { style: 'long' }).formatToParts(duration);

  return parts.map((part, i) => {
    if (part.type === 'integer') {
      return <strong key={i}>{part.value}</strong>;
    }
    return <span key={i}>{part.value}</span>;
  });
}

Réutiliser les instances de formateur pour de meilleures performances

Créer un nouveau formateur pour chaque durée ajoute une surcharge. Créez le formateur une seule fois et réutilisez-le.

const formatter = new Intl.DurationFormat('en', { style: 'short' });

const durations = [
  { hours: 1, minutes: 30 },
  { hours: 2, minutes: 15 },
  { hours: 0, minutes: 45 }
];

durations.map(d => formatter.format(d));
// ["1 hr and 30 min", "2 hr and 15 min", "45 min"]

Ce modèle améliore les performances lors du formatage de nombreuses durées dans des boucles ou des rendus.

Migration depuis la construction manuelle de chaînes

Remplacez la concaténation manuelle de chaînes par l'API. Cela réduit le code et ajoute la localisation.

Avant :

function formatDuration(hours, minutes) {
  if (hours > 0 && minutes > 0) {
    return `${hours}h ${minutes}m`;
  } else if (hours > 0) {
    return `${hours}h`;
  } else {
    return `${minutes}m`;
  }
}

Après :

function formatDuration(hours, minutes, locale) {
  const duration = {};
  if (hours > 0) duration.hours = hours;
  if (minutes > 0) duration.minutes = minutes;

  return new Intl.DurationFormat(locale, { style: 'narrow' }).format(duration);
}

La version API gère automatiquement toute la logique conditionnelle et prend en charge plusieurs langues.

Migration depuis des bibliothèques

Les bibliothèques comme Moment.js et date-fns fournissent le formatage de durée mais augmentent la taille du bundle. L'API native élimine cette dépendance.

Remplacez le formatage de durée de Moment.js :

// Avant : Moment.js
const duration = moment.duration(6400, 'seconds');
const formatted = duration.hours() + 'h ' + duration.minutes() + 'm';

// Après : Intl.DurationFormat
const duration = {
  hours: Math.floor(6400 / 3600),
  minutes: Math.floor((6400 % 3600) / 60)
};
new Intl.DurationFormat('en', { style: 'narrow' }).format(duration);

Remplacez le formatage de durée de date-fns :

// Avant : date-fns
import { formatDuration, intervalToDuration } from 'date-fns';
const duration = intervalToDuration({ start: 0, end: 6400000 });
const formatted = formatDuration(duration);

// Après : Intl.DurationFormat
const ms = 6400000;
const duration = {
  hours: Math.floor(ms / 3600000),
  minutes: Math.floor((ms % 3600000) / 60000),
  seconds: Math.floor((ms % 60000) / 1000)
};
new Intl.DurationFormat('en', { style: 'long' }).format(duration);

L'API native fournit les mêmes fonctionnalités sans dépendances.

Support des navigateurs et polyfills

L'API Intl.DurationFormat est devenue Baseline en mars 2025. Elle fonctionne dans les dernières versions de Chrome, Edge, Firefox et Safari.

Vérifiez le support avant utilisation :

if (typeof Intl.DurationFormat !== 'undefined') {
  const formatter = new Intl.DurationFormat('en', { style: 'short' });
  return formatter.format(duration);
} else {
  // Solution de repli pour les navigateurs plus anciens
  return `${duration.hours}h ${duration.minutes}m`;
}

Pour un support plus large, utilisez un polyfill. Le projet FormatJS fournit @formatjs/intl-durationformat.

npm install @formatjs/intl-durationformat

Importez et appliquez le polyfill si nécessaire :

if (!Intl.DurationFormat) {
  await import('@formatjs/intl-durationformat/polyfill');
}

Le polyfill ajoute environ 15 Ko compressé. Chargez-le conditionnellement pour éviter la surcharge pour les navigateurs modernes.

Quand utiliser DurationFormat

Utilisez Intl.DurationFormat pour afficher le temps écoulé, le temps restant ou les mesures de durée. Cela inclut les lecteurs vidéo, les minuteurs, les comptes à rebours, les applications de suivi, les réservations de voyage et les affichages de durée de session.

Ne l'utilisez pas pour les dates, les heures ou les horodatages. Utilisez Intl.DateTimeFormat pour ceux-ci. Ne l'utilisez pas pour les expressions de temps relatif comme "il y a 2 heures". Utilisez Intl.RelativeTimeFormat pour celles-ci.

L'API formate les durées, pas les calculs de temps. Vous devez calculer vous-même les valeurs de durée à partir de dates, d'horodatages ou d'autres sources. Le formateur ne gère que l'affichage.