How to Use Intl.DurationFormat in JavaScript

The Intl.DurationFormat API provides a native, standardized mechanism in JavaScript for formatting time durations into localized, human-readable strings. This article explains the syntax, configuration options, and practical implementation patterns of Intl.DurationFormat, demonstrating how to format duration objects across various locales and presentation styles without relying on external libraries.

Understanding the Duration Object

Intl.DurationFormat consumes duration data structured as an object containing specific time units. These units correspond to the properties defined in the ECMAScript Temporal.Duration specification, though plain JavaScript objects are also supported.

The supported duration properties include:

Basic Syntax and Usage

To format a duration, initialize an instance of Intl.DurationFormat with an optional locale and options object, then call the format() method.

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

// Create a formatter for US English
const durationFormatter = new Intl.DurationFormat('en-US', { style: 'long' });

console.log(durationFormatter.format(duration));
// Output: "2 hours, 45 minutes, 30 seconds"

Formatting Styles

The style option controls the overall density and presentation of the formatted output. It accepts four values:

const duration = { hours: 1, minutes: 30, seconds: 0 };

console.log(new Intl.DurationFormat('en-US', { style: 'long' }).format(duration));
// "1 hour, 30 minutes, 0 seconds"

console.log(new Intl.DurationFormat('en-US', { style: 'short' }).format(duration));
// "1 hr, 30 mins, 0 secs"

console.log(new Intl.DurationFormat('en-US', { style: 'narrow' }).format(duration));
// "1h 30m 0s"

console.log(new Intl.DurationFormat('en-US', { style: 'digital' }).format(duration));
// "1:30:00"

Customizing Unit Display

You can customize individual unit visibility using display options such as hoursDisplay, minutesDisplay, or secondsDisplay. These accept values like 'auto' (default) or 'always'.

const duration = { hours: 0, minutes: 15, seconds: 0 };

const formatter = new Intl.DurationFormat('en-US', {
  style: 'short',
  hoursDisplay: 'always',
  secondsDisplay: 'auto'
});

console.log(formatter.format(duration));
// Output: "0 hr, 15 mins"

To handle sub-second precision, use fractionalDigits:

const duration = { seconds: 5, milliseconds: 450 };

const formatter = new Intl.DurationFormat('en-US', {
  style: 'digital',
  fractionalDigits: 2
});

console.log(formatter.format(duration));
// Output: "0:05.45"

Localization

Intl.DurationFormat automatically adjusts unit names, grammar, separators, and plurals based on the targeted BCP 47 language tag.

const duration = { days: 2, hours: 4, minutes: 10 };

// French (France)
const frFormatter = new Intl.DurationFormat('fr-FR', { style: 'long' });
console.log(frFormatter.format(duration));
// Output: "2 jours, 4 heures et 10 minutes"

// German (Germany)
const deFormatter = new Intl.DurationFormat('de-DE', { style: 'long' });
console.log(deFormatter.format(duration));
// Output: "2 Tage, 4 Stunden und 10 Minuten"

// Japanese (Japan)
const jaFormatter = new Intl.DurationFormat('ja-JP', { style: 'long' });
console.log(jaFormatter.format(duration));
// Output: "2日 4時間 10分"

Detailed Breakdown with formatToParts()

For UI implementations requiring custom styling on specific numbers or unit labels, formatToParts() returns an array of tokenized objects.

const duration = { hours: 1, minutes: 20 };
const formatter = new Intl.DurationFormat('en-US', { style: 'short' });

const parts = formatter.formatToParts(duration);
console.log(parts);
/*
Output:
[
  { type: 'integer', value: '1', unit: 'hour' },
  { type: 'unit', value: ' hr', unit: 'hour' },
  { type: 'literal', value: ', ' },
  { type: 'integer', value: '20', unit: 'minute' },
  { type: 'unit', value: ' mins', unit: 'minute' }
]
*/