Библиотека date-fns в базовой конфигурации не содержит
встроенной поддержки часовых поясов. Все операции выполняются в
локальном времени среды выполнения JavaScript или в UTC, в зависимости
от используемых методов Date. Для полноценной работы с
временными зонами применяется дополнительный пакет
date-fns-tz, расширяющий функциональность и предоставляющий
инструменты преобразования между UTC и локальными временными зонами.
Ключевая концепция заключается в разделении трёх представлений времени:
Asia/Almaty, Europe/Berlin)Работа с часовыми поясами требует установки дополнительного пакета:
npm install date-fns date-fns-tz
Импорт функций выполняется отдельно от основного пакета:
import { format, parseISO } from 'date-fns';
import { zonedTimeToUtc, utcToZonedTime, formatInTimeZone } from 'date-fns-tz';
Объект Date в JavaScript хранит момент времени в виде
количества миллисекунд с эпохи Unix (UTC). При выводе значения
автоматически преобразуются в локальную временную зону среды
выполнения.
const date = new Date('2026-01-01T12:00:00Z');
console.log(date.toString());
// локальное представление времени
console.log(date.toISOString());
// всегда UTC
Проблема возникает при необходимости отображать одно и то же событие в разных временных зонах или корректно сохранять пользовательский ввод из определённого региона.
Функция zonedTimeToUtc выполняет преобразование времени,
интерпретируемого в указанной временной зоне, в UTC.
import { zonedTimeToUtc } from 'date-fns-tz';
const dateInAlmaty = '2026-05-22 10:00:00';
const timeZone = 'Asia/Almaty';
const utcDate = zonedTimeToUtc(dateInAlmaty, timeZone);
console.log(utcDate.toISOString());
Date в UTCИспользование важно при сохранении пользовательского ввода в базе данных, где требуется единый стандарт хранения времени.
Функция utcToZonedTime позволяет получить объект
Date, интерпретируемый в рамках конкретной временной
зоны.
import { utcToZonedTime } from 'date-fns-tz';
const utcDate = new Date('2026-05-22T12:00:00Z');
const timeZone = 'Asia/Tokyo';
const zonedDate = utcToZonedTime(utcDate, timeZone);
console.log(zonedDate);
Важно учитывать, что сам объект Date не хранит
информацию о временной зоне. Преобразование влияет только на
интерпретацию при форматировании.
Наиболее практичный инструмент — formatInTimeZone. Он
позволяет сразу отобразить дату в нужной временной зоне без
промежуточных преобразований.
import { formatInTimeZone } from 'date-fns-tz';
const date = new Date('2026-05-22T12:00:00Z');
const timeZone = 'Europe/Berlin';
const result = formatInTimeZone(date, timeZone, 'yyyy-MM-dd HH:mm:ssXXX');
console.log(result);
DateВсе операции выполняются с использованием стандартов IANA Time Zone Database:
Примеры:
Asia/AlmatyEurope/MoscowAmerica/New_YorkAsia/TokyoИспользование сокращений (например, MSK,
PST) не поддерживается, поскольку они неоднозначны и
зависят от контекста.
formatInTimeZone поддерживает токены форматирования
date-fns, включая отображение смещения.
import { formatInTimeZone } from 'date-fns-tz';
const date = new Date('2026-05-22T12:00:00Z');
const formatted = formatInTimeZone(date, 'America/New_York', 'yyyy-MM-dd HH:mm:ss XXX');
Символ XXX отображает смещение относительно UTC,
например -04:00.
При работе с входными строками важно явно указывать, как интерпретируется исходное значение.
import { zonedTimeToUtc, formatInTimeZone } from 'date-fns-tz';
const input = '2026-12-01 09:00:00';
const sourceZone = 'Asia/Almaty';
const utc = zonedTimeToUtc(input, sourceZone);
const formattedInNY = formatInTimeZone(utc, 'America/New_York', 'yyyy-MM-dd HH:mm:ss');
Цепочка преобразований:
При использовании date-fns-tz автоматически учитываются
переходы Daylight Saving Time (DST). Это означает:
Пример:
formatInTimeZone(
new Date('2026-07-01T12:00:00Z'),
'Europe/Berlin',
'yyyy-MM-dd HH:mm:ss'
);
Летнее время будет учтено автоматически.
new Date('2026-05-22T12:00:00')
new Date('2026-05-22T12:00:00Z')
const utc = zonedTimeToUtc(userInput, userTimeZone);
const view = formatInTimeZone(eventDate, userTimeZone, 'dd.MM.yyyy HH:mm');
const londonTime = formatInTimeZone(date, 'Europe/London', 'HH:mm');
const tokyoTime = formatInTimeZone(date, 'Asia/Tokyo', 'HH:mm');
date-fns использует токены форматирования:
yyyy — годMM — месяцdd — деньHH — часы (24-часовой формат)mm — минутыss — секундыПри использовании с date-fns-tz форматирование
происходит уже в контексте выбранной временной зоны, а не локальной
среды выполнения.
Date не хранит временную зонуDateЭти ограничения компенсируются функциями date-fns-tz,
которые выполняют вычисления смещений на уровне форматирования и
преобразования.