В основе работы с датой и временем в FormatJS лежит стандартный
объект Date и возможности Intl.DateTimeFormat.
Важная особенность заключается в том, что Date в JavaScript
не хранит часовой пояс как отдельное поле. Внутреннее представление
всегда основано на UTC, а отображение зависит от параметров
форматирования.
Фактически одно и то же значение времени может быть представлено по-разному в зависимости от выбранного часового пояса:
timeZone;Intl.DateTimeFormat.FormatJS использует эти механизмы через высокоуровневые API, обеспечивая единый подход к локализации.
FormatJS поддерживает ICU MessageFormat, где форматирование даты и времени может быть встроено прямо в строки сообщений.
Пример базового использования:
import {FormattedDate} from 'react-intl';
<FormattedDate value={Date.now()} />
По умолчанию используется локальный часовой пояс окружения выполнения кода.
Добавление явного формата времени:
<FormattedDate
value={Date.now()}
year="numeric"
month="long"
day="2-digit"
hour="2-digit"
minute="2-digit"
/>
Ключевой механизм работы с часовыми поясами — параметр
timeZone, который проксируется в
Intl.DateTimeFormat.
<FormattedDate
value={Date.now()}
timeZone="UTC"
/>
или
import {useIntl} from 'react-intl';
const intl = useIntl();
intl.formatDate(Date.now(), {
timeZone: 'Europe/Berlin',
year: 'numeric',
month: '2-digit',
day: '2-digit'
});
Использование timeZone позволяет фиксировать отображение
времени независимо от локального окружения пользователя.
FormatJS предоставляет низкоуровневый API через
intl.formatDate, который оборачивает
Intl.DateTimeFormat.
intl.formatDate(new Date('2026-01-10T12:00:00Z'), {
timeZone: 'Asia/Almaty',
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
Параметр timeZone влияет на интерпретацию исходного
UTC-времени. Важно учитывать, что исходная дата всегда рассматривается
как момент времени в UTC, если явно не указано обратное.
При отсутствии timeZone используется системный часовой
пояс:
intl.formatDate(Date.now());
При наличии timeZone результат становится
детерминированным:
intl.formatDate(Date.now(), { timeZone: 'UTC' });
Это особенно важно в следующих сценариях:
react-intl предоставляет компоненты, которые
автоматически используют Intl API.
import {FormattedDate, FormattedTime} from 'react-intl';
<FormattedDate
value={Date.now()}
timeZone="America/New_York"
/>
<FormattedTime
value={Date.now()}
timeZone="Asia/Tokyo"
/>
Компоненты FormattedDate и FormattedTime
позволяют задавать одинаковое время, но отображать его в разных часовых
поясах без ручных преобразований.
Встроенные возможности Intl.DateTimeFormat позволяют
выводить название временной зоны:
intl.formatDate(Date.now(), {
timeZone: 'Europe/London',
timeZoneName: 'long'
});
Варианты:
short — краткое обозначение (GMT+1, PDT);long — полное название (British Summer Time);shortOffset — смещение от UTC;longOffset — расширенное смещение.FormatJS передаёт эти параметры напрямую в Intl, не
изменяя их поведение.
В экосистеме FormatJS принято опираться на UTC как на базовый формат хранения.
Типичная схема:
timeZone в FormatJS.Пример:
const eventTime = '2026-05-01T18:00:00Z';
intl.formatDate(eventTime, {
timeZone: 'Asia/Almaty',
year: 'numeric',
month: 'short',
day: '2-digit',
hour: '2-digit',
minute: '2-digit'
});
Такой подход исключает неоднозначность при смене локали или перемещении пользователя между регионами.
При использовании IANA time zone identifiers (например,
Europe/Berlin, America/New_York) учитываются
правила перехода на летнее время.
intl.formatDate(new Date('2026-07-01T12:00:00Z'), {
timeZone: 'Europe/Berlin'
});
Переходы DST обрабатываются автоматически через внутренние механизмы
Intl.DateTimeFormat, поэтому ручная корректировка не
требуется.
SSR-рендеринг создаёт дополнительный слой сложности:
FormatJS позволяет минимизировать расхождения через явное указание
timeZone.
const markup = intl.formatDate(event.date, {
timeZone: 'UTC'
});
или через централизованную конфигурацию форматирования.
FormatJS позволяет задавать единые правила форматирования через
IntlProvider и кастомные форматтеры.
Хотя IntlProvider не управляет часовым поясом напрямую,
он служит точкой консолидации локализации, где можно централизованно
контролировать использование formatDate:
<IntlProvider locale="ru">
<App />
</IntlProvider>
Часовой пояс в таком случае обычно передаётся через параметры
форматирования или через обёртки над intl.
FormatJS не требует дополнительных библиотек для работы с
timezone-конвертацией, так как опирается на нативный
Intl.
new Intl.DateTimeFormat('ru-RU', {
timeZone: 'Asia/Almaty',
dateStyle: 'full',
timeStyle: 'short'
}).format(new Date());
FormatJS лишь предоставляет более структурированный доступ к этим возможностям через API локализации.
Некоторые ограничения связаны не с FormatJS, а с самим
Intl:
Также важно учитывать, что строка Date без указания зоны
интерпретируется по-разному в зависимости от среды выполнения.
В сложных приложениях часто применяется единый подход:
timeZone при форматировании;intl.formatDate.Пример утилиты:
const formatEventDate = (intl, date, zone) =>
intl.formatDate(date, {
timeZone: zone,
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
Такой слой обеспечивает консистентное отображение независимо от среды выполнения и географии пользователя.