Дата и время
Timestamp, UTC и местное время, ловушки Date, вычисления и форматирование через Intl.
Обновлено
Что такое Date в JavaScript
Объект Date представляет момент времени — внутри это просто число: миллисекунды, прошедшие с 1 января 1970 года, 00:00 UTC (timestamp).
const now = new Date()
now.getTime() // 1791460800000 — timestamp
Date.now() // то же самое, без объектаВсё, что вы видите как «8 октября, 14:30», — это интерпретация этого числа в часовом поясе. Отсюда почти все баги с датами.
UTC и местное время
| UTC | Местное время | |
|---|---|---|
| Что это | универсальное опорное время, без часового пояса | время в поясе устройства (Москва: UTC+3) |
| Где использовать | хранение, API, базы данных | только при выводе |
| Методы | getUTCHours(), toISOString() |
getHours(), toLocaleString() |
Золотое правило: храните и передавайте в UTC (ISO 8601), показывайте в местном времени.
new Date().toISOString() // '2026-10-08T11:30:00.000Z' — Z = UTCСоздание даты — ловушки
| Код | Результат | Ловушка |
|---|---|---|
new Date('2026-10-08') |
полночь UTC | в Москве покажет 03:00 |
new Date('2026-10-08T10:00') |
местное время | без Z = местное |
new Date('2026-10-08T10:00Z') |
время UTC | явно, надёжно |
new Date(2026, 9, 8) |
8 октября | месяцы начинаются с 0 |
new Date('08/10/2026') |
зависит от браузера | неоднозначный формат — не используйте |
Вычисления
const DAY = 24 * 60 * 60 * 1000
const diffDays = Math.round((b - a) / DAY) // разность двух Date даёт миллисекунды
const tomorrow = new Date(date)
tomorrow.setDate(tomorrow.getDate() + 1) // корректно обрабатывает конец месяцаВнимание: Date изменяемый — setDate меняет объект. Сначала сделайте копию (new Date(date)).
Из-за перехода на летнее время (во многих странах) сутки могут длиться 23 или 25 часов — поэтому при разнице в днях нужен Math.round.
Вывод через Intl
new Intl.DateTimeFormat('ru-RU', { dateStyle: 'long' }).format(date) // '8 октября 2026 г.'
new Intl.DateTimeFormat('ru-RU', { dateStyle: 'short', timeStyle: 'short' }).format(date)
new Intl.DateTimeFormat('ru-RU', { timeZone: 'Europe/London', timeStyle: 'short' }).format(date)
new Intl.RelativeTimeFormat('ru', { numeric: 'auto' }).format(-1, 'day') // 'вчера'
new Intl.RelativeTimeFormat('ru', { numeric: 'auto' }).format(3, 'day') // 'через 3 дня'Даты в Next.js — гидратация
Дата, отформатированная на сервере (пояс сервера, обычно UTC) и затем на клиенте (пояс пользователя), может дать разный текст → ошибка гидратации. Решения: форматировать с фиксированным timeZone или показывать относительное / местное время только в Client Component после монтирования.
Библиотеки и будущее
| Вариант | Когда |
|---|---|
Date + Intl |
большинство приложений |
| date-fns | много вычислений (добавить месяцы, начало недели) — маленькие функции с tree-shaking |
| Temporal (нативный, новый) | современный неизменяемый API с корректными часовыми поясами — замена Date, постепенно появляется в браузерах |
Коротко
Date= timestamp в UTC; всё остальное — интерпретация в часовом поясе.- Храните в UTC / ISO, показывайте локально через
Intl; месяцы с 0;Dateизменяемый. - Осторожно с гидратацией в Next; date-fns для вычислений, Temporal — на будущее.