Intl.DurationFormat: Locale-Aware Duration Formatting in JavaScript

Master the native browser API for formatting time durations that respects locale conventions without external dependencies.

Why Native Duration Formatting Matters

Before Intl.DurationFormat, developers had two choices: write custom formatting logic that manually handles pluralization, separators, and locale-specific patterns, or import external libraries like Moment.js or date-fns. Both approaches added complexity and bundle size to applications.

The native Intl.DurationFormat API eliminates these concerns by providing browser-optimized, locale-aware duration formatting out of the box. Since reaching Baseline status in March 2025, it's supported across all major browsers, making it production-ready for modern web applications.

Implementing proper localization contributes to better SEO performance by improving user experience for international audiences and reducing bounce rates from frustrated users who encounter poorly formatted time displays.

Browser Support Status

  • Chrome: Full support since version 133+
  • Firefox: Full support since version 134+
  • Safari: Full support since version 17+
  • Edge: Full support since matching Chromium version

For legacy browser support, the FormatJS polyfill provides compatibility while you transition.

Basic DurationFormat Usage
1const duration = {2 hours: 2,3 minutes: 30,4 seconds: 455};6 7// Default formatting (short style)8new Intl.DurationFormat('en-US').format(duration);9// "2 hr, 30 min and 45 sec"10 11// Long style for accessibility12new Intl.DurationFormat('en-US', { style: 'long' }).format(duration);13// "2 hours, 30 minutes and 45 seconds"14 15// Narrow style for compact spaces16new Intl.DurationFormat('en-US', { style: 'narrow' }).format(duration);17// "2h 30m 45s"

Core Concepts: Duration Objects

The Intl.DurationFormat API works with plain JavaScript objects that represent durations. Each time unit is optional--you only need to include the units relevant to your use case.

Duration Object Structure

const duration = {
 years: 1,
 months: 3,
 weeks: 2,
 days: 5,
 hours: 20,
 minutes: 45,
 seconds: 30,
 milliseconds: 123,
 microseconds: 456,
 nanoseconds: 789
};

The API automatically omits units with zero values and formats only the units you provide. This makes it flexible for everything from displaying video timestamps to showing project timelines. For teams building AI-powered applications, this native formatting integrates seamlessly with modern JavaScript ecosystems.

Constructor Parameters

The Intl.DurationFormat constructor accepts two parameters:

  1. locales: A string or array of locale identifiers (e.g., 'en-US', ['fr-FR', 'de-DE'])
  2. options: Configuration object for styling and display preferences

Style Options

The style option controls the verbosity of the formatted output. Choose based on your UI constraints and accessibility requirements.

Style Comparison

StyleExample OutputUse Case
short"1 hr, 30 min"Standard interfaces
long"1 hour, 30 minutes"Accessibility, formal contexts
narrow"1h 30m"Space-constrained UIs

Display Unit Selection

You can also specify which units to include in the output:

new Intl.DurationFormat('en-US', {
 style: 'long',
 hours: 'numeric',
 minutes: 'numeric',
 seconds: 'numeric'
}).format({ hours: 2, minutes: 30 });
// "2 hours and 30 minutes"

Method Reference

format() -- Simple String Output

The format() method is your go-to for most use cases. It returns a fully formatted duration string ready for display.

const duration = { hours: 1, minutes: 46, seconds: 40 };
const formatter = new Intl.DurationFormat('fr-FR', { style: 'long' });

formatter.format(duration);
// "1 heure, 46 minutes et 40 secondes"

formatToParts() -- Structured Output

When you need fine-grained control over styling, formatToParts() returns an array of objects describing each part of the formatted string.

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

formatter.formatToParts(duration);
// [
// { type: 'integer', value: '1', unit: 'hour' },
// { type: 'literal', value: ' ', unit: 'hour' },
// { type: 'unit', value: 'hr', unit: 'hour' },
// { type: 'literal', value: ', ', unit: 'minute' },
// { type: 'integer', value: '30', unit: 'minute' },
// { type: 'literal', value: ' ', unit: 'minute' },
// { type: 'unit', value: 'min', unit: 'minute' }
// ]

resolvedOptions() -- Configuration Discovery

Returns the effective options after locale negotiation, useful for debugging.

const formatter = new Intl.DurationFormat('en-US', { style: 'short' });
formatter.resolvedOptions();
// { locale: 'en-US', style: 'short', ... }

Internationalization in Practice

The real power of Intl.DurationFormat is its automatic handling of locale-specific conventions. Different languages have different rules for pluralization, conjunction, and unit formatting. This built-in internationalization capability saves hours of development time.

Multi-Locale Examples

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

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

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

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

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

// Norwegian
new Intl.DurationFormat('no', { style: 'long' }).format(duration);
// "1 år, 20 timer, 15 minutter og 35 sekunder"

// Swahili
new Intl.DurationFormat('sw', { style: 'long' }).format(duration);
// "saa 1, dakika 46 na sekunde 40"

Automatic Language Features

  • Pluralization: Automatically handles languages with complex plural rules (Slavic, Arabic)
  • Conjunctions: Respects locale-specific conjunction patterns (English "and" vs. other separators)
  • Unit Names: Uses correct localized unit terminology
  • Direction: Respects RTL text direction for languages like Arabic and Hebrew

Performance and Optimization

Efficient Formatter Reuse

Creating an Intl.DurationFormat instance has overhead. Reuse instances across your application for optimal performance. This pattern is especially important in high-traffic web applications where every millisecond counts.

// ❌ Avoid: Creating formatter on every call
function formatDuration(duration) {
 const formatter = new Intl.DurationFormat('en-US');
 return formatter.format(duration);
}

// ✅ Better: Reuse formatter instance
const durationFormatter = new Intl.DurationFormat('en-US', {
 style: 'long'
});

function formatDuration(duration) {
 return durationFormatter.format(duration);
}

Bundle Size Comparison

SolutionBundle Size (gzip)Format Speed
Intl.DurationFormat~0KB (native)Fastest
Moment.js~70KBSlower
date-fns~15KBModerate

Performance Tips

  • Create formatters at module level or with memoization
  • Cache formatters by locale/configuration combination
  • Use formatToParts() sparingly--it's slower than format()
  • For high-frequency updates (video progress), create formatter once and reuse

Explore more web development resources for performance optimization techniques.

Next.js Integration Pattern
1'use client';2 3import { useMemo } from 'react';4 5interface DurationDisplayProps {6 hours: number;7 minutes: number;8 seconds: number;9 locale?: string;10}11 12export function DurationDisplay({13 hours,14 minutes,15 seconds,16 locale = 'en-US'17}: DurationDisplayProps) {18 const formatter = useMemo(() => {19 return new Intl.DurationFormat(locale, {20 style: 'long',21 hours: 'numeric',22 minutes: 'numeric',23 seconds: 'numeric'24 });25 }, [locale]);26 27 const formatted = formatter.format({ hours, minutes, seconds });28 29 return <span className="duration-display">{formatted}</span>;30}

Best Practices and Common Patterns

Recommended Configuration Patterns

Video Player Time Display

const videoTimeFormatter = new Intl.DurationFormat('en-US', {
 style: 'short',
 hours: 'numeric',
 minutes: 'numeric',
 seconds: 'numeric'
});

Progress/Elapsed Time

const progressFormatter = new Intl.DurationFormat('en-US', {
 style: 'narrow',
 hours: 'numeric',
 minutes: 'numeric'
});

Accessibility-Focused Display

const accessibleFormatter = new Intl.DurationFormat('en-US', {
 style: 'long',
 hours: 'numeric',
 minutes: 'numeric',
 seconds: 'numeric'
});

Feature Detection Pattern

function supportsDurationFormat() {
 try {
 new Intl.DurationFormat('en-US');
 return true;
 } catch {
 return false;
 }
}

Frequently Asked Questions

Ready to Modernize Your Web Application?

We build custom web applications using Next.js and modern JavaScript APIs that deliver exceptional performance and user experiences.