В библиотеке Luxon объект DateTime всегда содержит:
Одна и та же временная точка может отображаться по-разному в зависимости от зоны:
import { DateTime } from 'luxon';
const dt = DateTime.fromISO('2025-03-10T12:00:00', {
zone: 'UTC'
});
console.log(dt.toString());
// 2025-03-10T12:00:00.000Z
После смены зоны тот же момент времени может выглядеть иначе:
const moscow = dt.setZone('Europe/Moscow');
console.log(moscow.toString());
// 2025-03-10T15:00:00.000+03:00
Время изменилось с 12:00 на 15:00, но сама
временная точка осталась прежней.
Именно вокруг этого поведения строится различие между
setZone(), toUTC() и
toLocal().
Метод setZone() переводит объект DateTime в
другую временную зону.
dt.setZone('Europe/Berlin')
setZone() сохраняет исходный момент времени.
Меняется только способ отображения даты и времени.
const utc = DateTime.fromISO(
'2025-06-01T12:00:00',
{ zone: 'UTC' }
);
const tokyo = utc.setZone('Asia/Tokyo');
console.log(utc.toISO());
// 2025-06-01T12:00:00.000Z
console.log(tokyo.toISO());
// 2025-06-01T21:00:00.000+09:00
Исходный момент:
12:00 UTC
После перевода в Токио:
21:00 UTC+9
Это одна и та же временная точка.
Изменилось только представление времени.
setZone() работает по следующему принципу:
Условно:
timestamp = const
zone = newZone
localTime = recalculated
const a = DateTime.fromISO(
'2025-01-01T12:00:00',
{ zone: 'UTC' }
);
const b = a.setZone('Europe/Moscow');
console.log(a.toMillis());
console.log(b.toMillis());
Результат:
1735732800000
1735732800000
Timestamp одинаковый.
Метод toUTC() — специализированная версия
setZone().
Фактически:
dt.toUTC()
эквивалентно:
dt.setZone('UTC')
const local = DateTime.fromISO(
'2025-08-20T18:00:00',
{ zone: 'Europe/Berlin' }
);
const utc = local.toUTC();
console.log(local.toString());
// 2025-08-20T18:00:00.000+02:00
console.log(utc.toString());
// 2025-08-20T16:00:00.000Z
Берлин летом использует UTC+2.
Следовательно:
18:00 Berlin
=
16:00 UTC
Timestamp не изменился.
Метод toLocal() переводит время в локальную системную
зону.
Фактически:
dt.toLocal()
аналогичен:
dt.setZone(systemZone)
где systemZone — часовой пояс операционной системы.
const utc = DateTime.utc(2025, 5, 1, 12);
const local = utc.toLocal();
console.log(local.toString());
Если системная зона:
Asia/Almaty
результат может быть:
2025-05-01T17:00:00.000+05:00
Используется для перевода времени в конкретную зону.
dt.setZone('America/New_York')
Быстрый способ перевести время в UTC.
dt.toUTC()
Быстрый способ перевести время в системную локальную зону.
dt.toLocal()
| Метод | Назначение | Меняется timestamp |
|---|---|---|
setZone() |
Перевод в любую зону | Нет |
toUTC() |
Перевод в UTC | Нет |
toLocal() |
Перевод в локальную зону | Нет |
По умолчанию setZone() сохраняет момент времени.
Но поведение можно изменить:
setZone(zone, { keepLocalTime: true })
Это один из самых сложных и важных моментов в Luxon.
Стандартное поведение:
const dt = DateTime.fromISO(
'2025-06-01T10:00:00',
{ zone: 'UTC' }
);
const result = dt.setZone('Europe/Moscow');
console.log(result.toString());
// 2025-06-01T13:00:00.000+03:00
Сохранился timestamp.
Изменилось отображение часов.
const dt = DateTime.fromISO(
'2025-06-01T10:00:00',
{ zone: 'UTC' }
);
const result = dt.setZone(
'Europe/Moscow',
{ keepLocalTime: true }
);
console.log(result.toString());
// 2025-06-01T10:00:00.000+03:00
Теперь локальное время осталось 10:00.
Но timestamp изменился.
Без опции:
10:00 UTC
=
13:00 Moscow
С опцией:
10:00 Moscow
То есть Luxon создаёт совершенно другую временную точку.
const a = DateTime.fromISO(
'2025-06-01T10:00:00',
{ zone: 'UTC' }
);
const b = a.setZone(
'Europe/Moscow',
{ keepLocalTime: true }
);
console.log(a.toMillis());
console.log(b.toMillis());
Значения будут разными.
Например:
Встреча начинается в 10:00
Пользователь хочет:
10:00 по Нью-Йорку
вместо
10:00 по Лондону
В этом случае требуется сохранить локальные часы, а не timestamp.
Для:
В таких задачах необходимо сохранять абсолютный момент времени.
Неверное ожидание:
dt.setZone('UTC')
Многие предполагают, что время на часах не изменится.
Но Luxon сохраняет timestamp.
Поэтому часы пересчитываются.
const dt = DateTime.fromISO(
'2025-06-01T12:00:00',
{ zone: 'Europe/Moscow' }
);
console.log(dt.toUTC().toString());
Результат:
2025-06-01T09:00:00.000Z
Это корректно.
Потому что:
12:00 Moscow
=
09:00 UTC
dt.setZone('UTC')
Меняется отображение.
DateTime.fromObject(
{
year: 2025,
month: 6,
day: 1,
hour: 12
},
{
zone: 'UTC'
}
)
Создаётся новый timestamp.
setZone() поддерживает фиксированные смещения:
dt.setZone('UTC+3')
или:
dt.setZone('UTC-5')
const dt = DateTime.utc();
const zone = dt.setZone('UTC+6');
console.log(zone.toString());
DST (Daylight Saving Time) особенно важен при переводе зон.
const winter = DateTime.fromISO(
'2025-01-10',
{ zone: 'Europe/Berlin' }
);
const summer = DateTime.fromISO(
'2025-07-10',
{ zone: 'Europe/Berlin' }
);
console.log(winter.offset);
// 60
console.log(summer.offset);
// 120
При переводе Luxon автоматически учитывает DST.
const utc = DateTime.utc(2025, 7, 1, 12);
const berlin = utc.setZone('Europe/Berlin');
console.log(berlin.toString());
Результат будет учитывать летнее время.
console.log(dt.zoneName);
console.log(dt.offset);
Результат в минутах:
180
означает:
UTC+3
console.log(DateTime.local().zoneName);
const createdAt = DateTime.utc();
const local = createdAt.toLocal();
const event = DateTime.fromISO(
'2025-12-01T15:00:00',
{ zone: 'UTC' }
);
event.setZone('Asia/Tokyo')
event.setZone('America/New_York')
Событие остаётся тем же самым.
Иногда требуется не перевод времени, а именно перенос.
Например:
09:00 London
→
09:00 Tokyo
Тогда используется:
dt.setZone('Asia/Tokyo', {
keepLocalTime: true
})
const dt = DateTime.fromISO(
'2025-01-01T09:00:00',
{ zone: 'Europe/London' }
);
console.log(
dt.setZone('Asia/Tokyo').toString()
);
Результат:
18:00 Tokyo
console.log(
dt.setZone(
'Asia/Tokyo',
{ keepLocalTime: true }
).toString()
);
Результат:
09:00 Tokyo
Это уже другой timestamp.
Когда требуется:
Когда требуется:
Когда требуется:
timestamp сохраняется
часы пересчитываются
часы сохраняются
timestamp изменяется
setZone('UTC')
setZone(systemZone)