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#
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')
}