A spec-compliant polyfill for Intl.DurationFormat
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 stringformatToParts(duration)- Format a duration and return an array of partsresolvedOptions()- Return resolved formatting optionssupportedLocalesOf(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,daysDisplayhoursDisplay,minutesDisplay,secondsDisplaymillisecondsDisplay,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#
Global import#
import '@formatjs/intl-durationformat/polyfill.js'
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"}
// ]
Info
The global import does not include TypeScript type declarations. For TypeScript projects, we recommend using ES module imports instead.
If you choose to use the global import, in order to prevent type errors, you must manually include the corresponding type declaration files (.d.ts) in your project.
ES Modules#
import {DurationFormat} from '@formatjs/intl-durationformat'
const formatter = new DurationFormat('en', {
style: 'long',
hours: 'numeric',
minutes: 'numeric',
seconds: 'numeric',
})
formatter.format({hours: 3, minutes: 25, seconds: 7})
// "3 hours, 25 minutes, 7 seconds"
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')
}