A spec-compliant polyfill for Intl.DurationFormat

npm Version size

ECMA-402 Spec Compliance

This package implements the Stage 4 Intl.DurationFormat specification, which is included in ECMA-402 12th Edition (June 2025). The implementation is fully spec-compliant with all features.

Specification Details

  • TC39 Proposal: Intl.DurationFormat
  • Stage: Stage 4 (Finalized)
  • ECMA-402 Edition: 12th Edition (June 2025)
  • Spec Pages: 57-62

✅ All Features Implemented

Core Methods

  • format(duration) - Format a duration object to a localized string
  • formatToParts(duration) - Format a duration and return an array of parts
  • resolvedOptions() - Return resolved formatting options
  • supportedLocalesOf(locales) - Check which locales are supported

Style Options

All 4 style values are supported:

  • 'long' (default) - Full format (e.g., "3 hours, 25 minutes")
  • 'short' - Abbreviated format (e.g., "3 hr, 25 min")
  • 'narrow' - Most compact format (e.g., "3h 25m")
  • 'digital' - Digital clock format (e.g., "3:25:00")

Duration Units

All 10 duration fields are fully supported:

  • Years (years)
  • Months (months)
  • Weeks (weeks)
  • Days (days)
  • Hours (hours)
  • Minutes (minutes)
  • Seconds (seconds)
  • Milliseconds (milliseconds)
  • Microseconds (microseconds)
  • Nanoseconds (nanoseconds)

Each unit supports multiple format styles:

  • 'long', 'short', 'narrow' - Text-based formats
  • 'numeric' - Numeric format
  • '2-digit' - Two-digit numeric format (for hours, minutes, seconds)

Display Control

Per-unit display options with values 'always' | 'auto':

  • yearsDisplay, monthsDisplay, weeksDisplay, daysDisplay
  • hoursDisplay, minutesDisplay, secondsDisplay
  • millisecondsDisplay, microsecondsDisplay, nanosecondsDisplay

When set to 'auto', zero values are omitted. When set to 'always', zero values are included.

Additional Options

  • fractionalDigits - Control decimal precision (0-9 digits)
  • numberingSystem - Alternative numbering systems (50+ supported)
  • localeMatcher - Locale resolution algorithm ('best fit' or 'lookup')

Example Usage

import '@formatjs/intl-durationformat/polyfill'

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

formatter.format({hours: 3, minutes: 25, seconds: 7})
// "3 hours, 25 minutes, 7 seconds"

// Digital format
const digital = new Intl.DurationFormat('en', {style: 'digital'})
digital.format({hours: 1, minutes: 30, seconds: 45})
// "1:30:45"

// formatToParts
const parts = formatter.formatToParts({hours: 2, minutes: 30})
// [
//   {type: "integer", value: "2", unit: "hour"},
//   {type: "literal", value: " hours, "},
//   {type: "integer", value: "30", unit: "minute"},
//   {type: "literal", value: " minutes"}
// ]

Installation

npm i @formatjs/intl-durationformat

Requirements

Usage

Simple

import '@formatjs/intl-durationformat/polyfill.js'

Dynamic import + capability detection

async function polyfill(locale: string) {
  const unsupportedLocale = shouldPolyfill(locale)
  // This locale is supported
  if (!unsupportedLocale) {
    return
  }
  // Load the polyfill 1st BEFORE loading data
  await import('@formatjs/intl-durationformat/polyfill-force.js')
}