A spec-compliant polyfill for Intl.DateTimeFormat fully tested by the official ECMAScript Conformance test suite

npm Version size

Features

Installation

npm i @formatjs/intl-datetimeformat

Requirements

This package requires the following capabilities:

Usage

Via polyfill-fastly.io

You can use polyfill-fastly.io URL Builder to create a polyfill script tag for Intl.DateTimeFormat. By default the created URL does not come with any locale data. In order to add locale data, append Intl.DateTimeFormat.~locale.<locale>, as well as locale data for any required polyfills, to your list of features. For example:

<!-- Polyfill Intl.DateTimeFormat, its dependencies & `en` locale data -->
<script src="https://polyfill-fastly.io/v3/polyfill.min.js?features=Intl.DateTimeFormat,Intl.DateTimeFormat.~locale.en,Intl.NumberFormat.~locale.en"></script>

Simple

import '@formatjs/intl-datetimeformat/polyfill.js'
import '@formatjs/intl-datetimeformat/locale-data/en.js' // locale-data for en
import '@formatjs/intl-datetimeformat/add-all-tz.js' // Add ALL tz data

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-datetimeformat/polyfill-force.js')

  // Parallelize CLDR data loading
  const dataPolyfills = [
    import('@formatjs/intl-datetimeformat/add-all-tz.js'),
    import(`@formatjs/intl-datetimeformat/locale-data/${unsupportedLocale}.js`),
  ]
  await Promise.all(dataPolyfills)
}

Adding IANA Timezone Database

We provide 2 pre-processed IANA Timezone:

Full: contains ALL Timezone from IANA database

import '@formatjs/intl-datetimeformat/polyfill.js'
import '@formatjs/intl-datetimeformat/add-all-tz.js'
import '@formatjs/intl-datetimeformat/polyfill.js'
import '@formatjs/intl-datetimeformat/add-golden-tz.js'

UTC Offset Timezones

This polyfill supports UTC offset timezone identifiers as specified in ECMA-402 (ES2026). You can use offset-based timezone strings in addition to IANA timezone names.

Supported Formats

The following UTC offset formats are supported:

  • ±HH:MM - e.g., "+01:00", "-05:00" (recommended format)
  • ±HHMM - e.g., "+0100", "-0500"
  • ±HH - e.g., "+01", "-05"
  • ±HH:MM:SS - e.g., "+01:30:45" (with seconds)
  • ±HH:MM:SS.sss - e.g., "+01:30:45.123" (with fractional seconds)

All offset formats are automatically canonicalized to ±HH:MM format (with seconds/fractional seconds preserved if non-zero).

Usage Example

import '@formatjs/intl-datetimeformat/polyfill.js'
import '@formatjs/intl-datetimeformat/locale-data/en.js'

// Using UTC offset timezone
const formatter = new Intl.DateTimeFormat('en-GB', {
  timeZone: '+01:00',
  year: 'numeric',
  month: 'numeric',
  day: 'numeric',
  hour: 'numeric',
  minute: 'numeric',
})

console.log(formatter.format(new Date('2024-01-01T00:00:00Z')))
// Output: "01/01/2024, 01:00"

// Works with @date-fns/tz and other libraries
const dtf = new Intl.DateTimeFormat('en-GB', {
  timeZone: '+01:00',
  hour: 'numeric',
  timeZoneName: 'longOffset',
})

Compatibility

  • UTC offset timezones work without loading any timezone data (add-all-tz.js or add-golden-tz.js)
  • Compatible with libraries like @date-fns/tz in React Native/Hermes environments
  • Follows the same behavior as Chrome and Node.js 22+ native implementations

Default Timezone

Since JS Engines do not expose default timezone, there's currently no way for us to detect local timezone that a browser is in. Therefore, the default timezone in this polyfill is UTC.

You can change this by either calling __setDefaultTimeZone or always explicitly pass in timeZone option for accurate date time calculation.

Since __setDefaultTimeZone is not in the spec, you should make sure to check for its existence before calling it & after tz data has been loaded, e.g:

import '@formatjs/intl-datetimeformat/polyfill.js'
import '@formatjs/intl-datetimeformat/add-all-tz.js'

if ('__setDefaultTimeZone' in Intl.DateTimeFormat) {
  Intl.DateTimeFormat.__setDefaultTimeZone('America/Los_Angeles')
}

Tests

This library is fully test262-compliant.