Intl.DateTimeFormat — часть спецификации ECMAScript
Internationalization API (Intl), предназначенная для
локализованного форматирования дат и времени. Современные браузеры и
среды выполнения JavaScript поддерживают этот API нативно, однако в ряде
случаев требуется полифилл:
Полифилл из экосистемы FormatJS предоставляет совместимую реализацию
Intl.DateTimeFormat, соответствующую современным
спецификациям ECMA-402.
Основной пакет:
npm install @formatjs/intl-datetimeformat
Дополнительные пакеты:
npm install @formatjs/intl-locale
npm install @formatjs/intl-getcanonicallocales
Для загрузки данных локализации:
npm install @formatjs/intl-datetimeformat/locale-data/en
npm install @formatjs/intl-datetimeformat/locale-data/ru
Для поддержки таймзон:
npm install @formatjs/intl-datetimeformat/add-all-tz
Полифилл состоит из нескольких уровней:
| Компонент | Назначение |
|---|---|
polyfill |
Добавляет API при отсутствии |
polyfill-force |
Принудительно заменяет нативную реализацию |
locale-data |
Данные локализации |
add-all-tz |
База таймзон |
should-polyfill |
Проверка необходимости полифилла |
import '@formatjs/intl-datetimeformat/polyfill';
import '@formatjs/intl-datetimeformat/locale-data/ru';
const formatter = new Intl.DateTimeFormat('ru');
console.log(formatter.format(new Date()));
FormatJS предоставляет утилиту shouldPolyfill.
import {shouldPolyfill} from '@formatjs/intl-datetimeformat/should-polyfill';
if (shouldPolyfill()) {
await import('@formatjs/intl-datetimeformat/polyfill');
await import('@formatjs/intl-datetimeformat/locale-data/ru');
}
Подобный подход уменьшает размер итогового бандла.
Некоторые среды содержат частичную или некорректную реализацию
Intl.DateTimeFormat. В таких случаях используется
polyfill-force.
import '@formatjs/intl-datetimeformat/polyfill-force';
Теперь даже при наличии встроенного API будет использоваться реализация FormatJS.
Полифилл не включает все локали автоматически. Каждая локаль импортируется отдельно.
import '@formatjs/intl-datetimeformat/locale-data/en';
import '@formatjs/intl-datetimeformat/locale-data/ru';
import '@formatjs/intl-datetimeformat/locale-data/en';
import '@formatjs/intl-datetimeformat/locale-data/ru';
import '@formatjs/intl-datetimeformat/locale-data/de';
const formatter = new Intl.DateTimeFormat('ru', {
dateStyle: 'full'
});
console.log(formatter.format(new Date()));
Результат:
понедельник, 15 января 2026 г.
const formatter = new Intl.DateTimeFormat('ru', {
timeStyle: 'medium'
});
console.log(formatter.format(new Date()));
const formatter = new Intl.DateTimeFormat('ru', {
dateStyle: 'long',
timeStyle: 'short'
});
console.log(formatter.format(new Date()));
const formatter = new Intl.DateTimeFormat('ru', {
day: '2-digit',
month: 'long',
year: 'numeric'
});
console.log(formatter.format(new Date()));
const formatter = new Intl.DateTimeFormat('ru', {
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
});
console.log(formatter.format(new Date()));
const formatter = new Intl.DateTimeFormat('ru', {
timeZone: 'UTC',
timeStyle: 'long'
});
console.log(formatter.format(new Date()));
По умолчанию полифилл не содержит полной информации о таймзонах.
import '@formatjs/intl-datetimeformat/add-all-tz';
Вместо полной базы можно использовать сокращённый вариант.
import '@formatjs/intl-datetimeformat/add-golden-tz';
Такой вариант уменьшает размер бандла.
const us = new Intl.DateTimeFormat('en-US');
console.log(us.format(new Date()));
const de = new Intl.DateTimeFormat('de-DE');
console.log(de.format(new Date()));
const jp = new Intl.DateTimeFormat('ja-JP');
console.log(jp.format(new Date()));
formatToPartsМетод formatToParts возвращает структуру форматированной
даты.
const formatter = new Intl.DateTimeFormat('ru', {
dateStyle: 'long'
});
console.log(formatter.formatToParts(new Date()));
Пример результата:
[
{ type: 'day', value: '15' },
{ type: 'literal', value: ' ' },
{ type: 'month', value: 'января' }
]
formatToParts позволяет создавать кастомное
форматирование.
const formatter = new Intl.DateTimeFormat('ru', {
hour: '2-digit',
minute: '2-digit'
});
const parts = formatter.formatToParts(new Date());
const values = Object.fromEntries(
parts.map(part => [part.type, part.value])
);
console.log(`${values.hour}:${values.minute}`);
Современные реализации поддерживают formatRange.
const formatter = new Intl.DateTimeFormat('ru', {
dateStyle: 'medium'
});
const start = new Date(2026, 0, 10);
const end = new Date(2026, 0, 15);
console.log(formatter.formatRange(start, end));
const formatter = new Intl.DateTimeFormat('ru', {
dateStyle: 'full'
});
console.log(
formatter.formatRangeToParts(start, end)
);
const formatter = new Intl.DateTimeFormat('ar', {
calendar: 'islamic'
});
console.log(formatter.format(new Date()));
const formatter = new Intl.DateTimeFormat('ja-JP-u-ca-japanese');
console.log(formatter.format(new Date()));
const formatter = new Intl.DateTimeFormat('ar', {
numberingSystem: 'arab'
});
console.log(formatter.format(new Date()));
const formatter = new Intl.DateTimeFormat('ru', {
hour: 'numeric',
hourCycle: 'h23'
});
console.log(formatter.format(new Date()));
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
hourCycle: 'h12'
});
console.log(formatter.format(new Date()));
resolvedOptionsМетод показывает итоговые настройки форматтера.
const formatter = new Intl.DateTimeFormat('ru');
console.log(formatter.resolvedOptions());
Пример результата:
{
locale: 'ru',
calendar: 'gregory',
numberingSystem: 'latn',
timeZone: 'UTC'
}
import '@formatjs/intl-datetimeformat/polyfill';
import '@formatjs/intl-datetimeformat/add-all-tz';
import '@formatjs/intl-datetimeformat/locale-data/ru';
Некоторые сборки Node.js содержат сокращённую ICU-базу
(small-icu), из-за чего:
Полифилл FormatJS устраняет эти ограничения.
async function loadLocale(locale) {
await import(
`@formatjs/intl-datetimeformat/locale-data/${locale}`
);
}
import '@formatjs/intl-datetimeformat/add-all-tz';
Полная база таймзон существенно увеличивает размер приложения.
import '@formatjs/intl-datetimeformat/add-golden-tz';
const formatter = new Intl.DateTimeFormat('ru', {
dateStyle: 'long'
});
function DateLabel({date}) {
return (
<span>
{formatter.format(date)}
</span>
);
}
Библиотека react-intl использует
Intl.DateTimeFormat внутри своих компонентов.
<FormattedDate
value={new Date()}
year="numeric"
month="long"
day="2-digit"
/>
При отсутствии нативной поддержки автоматически применяется полифилл.
Полифилл особенно актуален для:
| Браузер | Особенности |
|---|---|
| Internet Explorer | отсутствует современный Intl |
| Safari старых версий | частичная поддержка |
| Android WebView | ограниченная ICU |
| Старые Chromium | отсутствуют новые API |
Полифилл поддерживает:
formatformatToPartsformatRangeformatRangeToPartsНекоторые особенности зависят от объёма подключённых данных:
Внутри полифилл:
FormatJS основан на Unicode CLDR.
CLDR содержит:
| Возможность | Нативный API | FormatJS |
|---|---|---|
| Поддержка старых браузеров | Нет | Да |
| Единое поведение | Частично | Да |
| Настраиваемые данные | Нет | Да |
| Контроль локалей | Ограничен | Полный |
| Поддержка таймзон | Зависит от среды | Да |
import '@formatjs/intl-getcanonicallocales/polyfill';
import '@formatjs/intl-locale/polyfill';
import '@formatjs/intl-datetimeformat/polyfill';
import '@formatjs/intl-datetimeformat/add-golden-tz';
import '@formatjs/intl-datetimeformat/locale-data/en';
import '@formatjs/intl-datetimeformat/locale-data/ru';
console.log(typeof Intl.DateTimeFormat);
console.log(
Intl.DateTimeFormat.supportedLocalesOf([
'ru',
'fr',
'ja'
])
);
const formatter = new Intl.DateTimeFormat(
'th-TH-u-nu-thai'
);
console.log(formatter.format(new Date()));
const formatter = new Intl.DateTimeFormat('fr-FR', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit',
timeZone: 'Europe/Paris'
});
console.log(Intl.DateTimeFormat.toString());
console.log(
Intl.DateTimeFormat().resolvedOptions().timeZone
);
Ошибка:
Missing locale data
Причина:
import '@formatjs/intl-datetimeformat/polyfill';
без:
import '@formatjs/intl-datetimeformat/locale-data/ru';
Ошибка:
Invalid time zone specified
Причина — отсутствие базы таймзон.
Решение:
import '@formatjs/intl-datetimeformat/add-all-tz';
При серверном рендеринге важно:
global.Intl = require('@formatjs/intl-datetimeformat');
import '@formatjs/intl-datetimeformat/polyfill';
import '@formatjs/intl-datetimeformat/add-golden-tz';
import '@formatjs/intl-datetimeformat/locale-data/ru';
const formatter = new Intl.DateTimeFormat('ru', {
dateStyle: 'full',
timeStyle: 'long',
timeZone: 'Europe/Moscow'
});
console.log(
formatter.format(new Date())
);