TGViewer
Настоящий JavaScript Настоящий JavaScript @true_js · 5.89K subscribers
Post #3573 388
Temporal в JavaScript: даты без production-боли от Date

Date смешивает слишком много понятий: момент времени, локальное представление, таймзону окружения, парсинг строк и мутабельность. В итоге баги часто появляются не в unit-тестах, а в production: на DST-переходах, у пользователей из другой таймзоны или при переносе кода между Node.js и браузером.

Temporal решает это за счёт явного разделения сущностей:

• Temporal.Instant — точный момент времени, удобно хранить в UTC
• Temporal.ZonedDateTime — дата/время + IANA timezone
• Temporal.PlainDate — календарная дата без времени и таймзоны
• Temporal.PlainTime — время без даты
• Temporal.Duration — длительность
• Temporal.PlainDateTime — локальные дата и время без привязки к зоне

Главная идея: не притворяться, что «дата» — это одна универсальная сущность.

Пример с DST:

import { Temporal } from '@js-temporal/polyfill';

const meeting = Temporal.ZonedDateTime.from(
'2024-03-30T12:00:00+01:00[Europe/Berlin]'
);

console.log(meeting.add({ days: 1 }).toString());
// 2024-03-31T12:00:00+02:00[Europe/Berlin]

console.log(meeting.add({ hours: 24 }).toString());
// 2024-03-31T13:00:00+02:00[Europe/Berlin]


Это не одно и то же.

add({ days: 1 }) означает «завтра в это же локальное время».
add({ hours: 24 }) означает «через 24 реальных часа».

На переходе на летнее время день может быть не 24 часа. Temporal делает это различие явным, а Date обычно прячет проблему до момента, когда пользователи начинают жаловаться.

Ещё один важный кейс — несуществующее локальное время:

try {
Temporal.ZonedDateTime.from(
'2024-03-31T02:30[Europe/Berlin]',
{ disambiguation: 'reject' }
);
} catch {
console.log('Такого локального времени нет из-за DST');
}


В ночь перехода на летнее время 02:30 в Berlin может просто не существовать. В Date такие ситуации часто «нормализуются» молча. В Temporal можно явно выбрать стратегию: reject, earlier, later, compatible.

Практические правила для production:

1. Храните точный момент как Instant
Например, событие уже произошло или платёж создан.

2. Храните пользовательскую таймзону отдельно
Не GMT+3, а IANA zone: Europe/Berlin, Asia/Tbilisi, America/New_York.

3. Для бизнес-правил используйте календарные типы
День рождения — это PlainDate, а не Date в полночь UTC.
«Каждый день в 09:00 по Москве» — это локальное время + timezone, а не setInterval(24h).

4. Не заменяйте календарные операции миллисекундами
+ 86400000 — это не всегда «завтра». На DST это может быть 23 или 25 локальных часов.

5. Делайте неоднозначность явной
Если локальное время может не существовать или повторяться, выбирайте поведение явно через disambiguation.

Temporal особенно полезен там, где цена ошибки высокая: расписания, биллинг, бронирования, напоминания, cron-like задачи, SLA, отчёты по локальным дням.

Важно: поддержка Temporal зависит от runtime. Для production сейчас обычно используют polyfill @js-temporal/polyfill и постепенно готовятся к нативной поддержке.

Коротко: Date хорош для простых timestamp-операций, но плохо моделирует реальные бизнес-даты. Temporal заставляет выбрать правильную модель времени — и именно поэтому снижает количество багов на таймзонах и DST.
More from @true_js
  1. Oct 3, 2026Post #3963
  2. Oct 2, 2026😅 Айтишник отправил в одну компанию три одинаковых резюме и только одно дошло до финала О…
  3. Oct 2, 2026🤣 Правильно расставленные приоритеты в моей жизни би лайк: 💥 xCode Journal
  4. Oct 1, 2026🤯 Люди взбунтовались против «пыточной для ИИ» На GitHub заметили открытый проект AI Tortu…
  5. Sep 30, 2026Книга из переписки без сервера: canvas, jsPDF и брошюра для печати прямо в браузере Пет-пр…
  6. Sep 30, 2026Экономика клиентской разработки с AI С AI в клиентской разработке появился смысл делать то…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →