Temporal в ES2026: конец мучениям с датами в JavaScript
На заседании TC39 в марте 2026 года API Temporal достиг стадии Stage 4 и официально вошёл в спецификацию ECMAScript 2026. Так завершился путь, начавшийся ещё в 2017 году — почти десятилетие работы, — чтобы исправить одну из старейших болей языка: объект Date.
Проблема: Date так и не повзрослел
Любой, кто работал с датами в JavaScript, знает эту боль. Date изменяемый (mutable), не имеет настоящей поддержки часовых поясов и ведёт себя настолько запутанно, что стандартным решением было подключить тяжёлую стороннюю библиотеку вроде Moment.js — порой сотни килобайт данных о часовых поясах — лишь ради того, чтобы «прибавить два часа с учётом перехода на летнее время».
Знакомый итог: тихие ошибки в расчётах времени или полный отказ от Date.
Что изменилось: пространство имён Temporal
Temporal вводит новое пространство имён со специализированными типами, и каждое значение в нём неизменяемо (immutable) — любая операция возвращает новое значение, а не меняет исходное. Ключевые типы:
- Temporal.Instant — точный момент на глобальной шкале времени.
- Temporal.ZonedDateTime — дата и время, привязанные к конкретному часовому поясу, с корректной обработкой перехода на летнее время.
- Temporal.PlainDate, Temporal.PlainTime, Temporal.PlainDateTime — календарные значения без часового пояса (например, «24 июля» в отрыве от зоны).
- Temporal.Duration — длительность для арифметики без библиотек.
- Temporal.Now — явная точка входа для текущего момента.
Практический пример
import { Temporal } from '@js-temporal/polyfill';// пока нативная поддержка не появилась везде// Дата без часового поясаconst date = Temporal.PlainDate.from('2026-07-24');date.add({ days: 10 }).toString();// '2026-08-03' — значение неизменяемо, поэтому возвращается новое// Точный момент, привязанный к часовому поясуconst meeting = Temporal.ZonedDateTime.from({ timeZone: 'Asia/Riyadh', year: 2026, month: 7, day: 24, hour: 16, minute: 0,});// Перевод в другую зону — переход на летнее время учтён верноmeeting.withTimeZone('Europe/Moscow').toString();// Арифметика длительностей без внешних библиотекconst dur = Temporal.Duration.from({ hours: 3, minutes: 30 });meeting.add(dur).toString();// «Сейчас» стало явным и зависящим от зоныTemporal.Now.zonedDateTimeISO('Asia/Riyadh').toString();
Ключевое отличие: никакой скрытой мутации значений, а часовой пояс — полноценная часть типа, а не «прицеп» сбоку.
Нюансы из реальной практики
Temporal уже в спецификации, но поддержка ещё разворачивается:
- Браузеры: Firefox уже поставил его, браузеры на Chromium (Chrome, Edge) поддерживают начиная с Chromium 144. У Safari частичная поддержка в Technology Preview.
- TypeScript: версия 6.0 включает определения типов Temporal.
- Node.js: поддержка ожидается в будущем релизе; до тех пор используйте официальный
@js-temporal/polyfill.
Практическое правило: для продакшена сегодня опирайтесь на официальный полифил, пока нативная поддержка не появится во всех целевых средах, а затем уберите его без изменения кода.
Вывод
Temporal — не просто замена Date, а полное переосмысление того, как JavaScript работает со временем: неизменяемые значения, часовые пояса «из коробки» и встроенная арифметика длительностей. Переход на него снижает число ошибок и снимает зависимость от тяжёлых библиотек. Начните с полифила в одном проекте и пишите новую логику времени сразу на Temporal.
Если вы собираете современный набор инструментов, Temporal дополняет более широкую картину эволюции экосистемы — как и TypeScript 7 с его нативным компилятором.
Первоисточник: Предложение Temporal — TC39 (GitHub)