JavaScript Date

Встроенный объект Date в JavaScript долгое время остаётся базовым инструментом для работы с датой и временем. Он предоставляет возможность создавать временные метки, выполнять простые арифметические операции и форматировать дату через набор ограниченных методов.

Ключевая особенность Date заключается в том, что он основан на миллисекундах с 1 января 1970 года (UTC). Любая дата внутри JavaScript фактически хранится как число:

const now = new Date();
const timestamp = now.getTime();

Основные особенности Date

  • хранение времени в виде Unix timestamp в миллисекундах
  • автоматическая работа с локальной временной зоной окружения
  • базовые методы форматирования (toISOString, toString, toLocaleString)
  • ограниченная поддержка временных зон
  • отсутствие встроенной работы с календарными интервалами

Несмотря на универсальность, Date имеет ряд архитектурных проблем, которые становятся критичными в прикладных системах.

Проблемы стандартного Date API

1. Сложность работы с временными зонами

Date не хранит полноценную информацию о временной зоне. Он оперирует либо UTC, либо локальной зоной окружения:

const d = new Date();
d.getTimezoneOffset();

Это создаёт неоднозначности при:

  • работе с пользователями из разных регионов
  • серверных вычислениях
  • хранении и интерпретации дат в базе данных

2. Неудобная арифметика дат

Добавление дней, месяцев или лет требует ручной логики:

const d = new Date();
d.setDate(d.getDate() + 7);

Проблема проявляется при переходах через границы месяцев и лет, где поведение становится неочевидным.

3. Ограниченное форматирование

Стандартные методы Date не предоставляют гибкой локализации и шаблонов:

new Date().toLocaleString('ru-RU');

Однако контроль над форматом остаётся ограниченным и зависит от среды выполнения.

4. Изменяемость объекта

Date является мутируемым объектом. Любая операция изменяет исходный экземпляр:

const d1 = new Date();
const d2 = d1;
d2.setFullYear(2030);

Обе переменные указывают на один объект, что часто приводит к ошибкам.


Появление современных библиотек работы с датами

Для устранения ограничений Date появились специализированные библиотеки:

  • Moment.js (исторически популярная, но устаревающая)
  • Day.js (лёгкая альтернатива)
  • Luxon — современная библиотека с акцентом на immutable API и поддержку временных зон

Luxon создана как эволюция подхода к работе со временем, устраняющая фундаментальные недостатки Date.


Основная модель Luxon

Luxon базируется на трёх ключевых сущностях:

  • DateTime — основная единица времени
  • Duration — длительность
  • Interval — временной интервал

DateTime как центральная абстракция

import { DateTime } from "luxon";

const now = DateTime.now();

В отличие от Date, объект DateTime:

  • неизменяемый (immutable)
  • содержит информацию о временной зоне
  • поддерживает богатое форматирование
  • предоставляет цепочки методов

Создание объектов DateTime

Текущее время

const now = DateTime.now();

UTC время

const utc = DateTime.utc();

Создание из компонентов

const dt = DateTime.local(2026, 5, 23, 14, 30);

Создание из timestamp

const dt = DateTime.fromMillis(1716460800000);

Работа с временными зонами

Одно из ключевых преимуществ Luxon — полноценная поддержка IANA time zones.

const dt = DateTime.now().setZone("Asia/Almaty");

Переключение зон

const local = DateTime.now();
const tokyo = local.setZone("Asia/Tokyo");
const london = local.setZone("Europe/London");

Каждый объект остаётся независимым и неизменяемым.


Форматирование дат

Luxon использует гибкую систему форматирования через toFormat.

const dt = DateTime.now();

dt.toFormat("yyyy-MM-dd HH:mm");

Основные токены форматирования

  • yyyy — год
  • MM — месяц
  • dd — день
  • HH — часы
  • mm — минуты
  • ss — секунды

Локализованное форматирование

dt.setLocale("ru").toLocaleString(DateTime.DATE_FULL);

Преобразование даты в строки

Luxon поддерживает несколько уровней сериализации.

ISO формат

dt.toISO();

JSON формат

dt.toJSON();

Человеко-читаемый формат

dt.toLocaleString(DateTime.DATETIME_MED);

Арифметика дат

Luxon решает проблему мутации через неизменяемые операции.

Добавление времени

const future = DateTime.now().plus({ days: 10 });

Вычитание времени

const past = DateTime.now().minus({ months: 2 });

Цепочки операций

const result = DateTime.now()
  .plus({ days: 3 })
  .minus({ hours: 5 })
  .setZone("Europe/Berlin");

Каждая операция возвращает новый объект.


Duration: работа с длительностью

Duration представляет промежуток времени независимо от конкретной даты.

import { Duration } from "luxon";

const dur = Duration.fromObject({ hours: 2, minutes: 30 });

Преобразование в миллисекунды

dur.as("milliseconds");

Сложение с DateTime

DateTime.now().plus(dur);

Interval: временные интервалы

Interval описывает диапазон между двумя точками времени.

import { Interval } from "luxon";

const start = DateTime.now();
const end = start.plus({ days: 5 });

const interval = Interval.fromDateTimes(start, end);

Проверка вхождения даты

interval.contains(DateTime.now());

Пересечение интервалов

interval.intersection(otherInterval);

Парсинг строк

Luxon умеет разбирать строки в DateTime.

ISO строки

DateTime.fromISO("2026-05-23T10:00:00");

Пользовательские форматы

DateTime.fromFormat("23-05-2026", "dd-MM-yyyy");

Unix timestamp

DateTime.fromSeconds(1716460800);

Сравнение Date и Luxon

Изменяемость

  • Date: mutable
  • Luxon: immutable

Временные зоны

  • Date: ограниченная поддержка
  • Luxon: полноценные IANA зоны

Форматирование

  • Date: базовое
  • Luxon: гибкое, локализуемое

Арифметика

  • Date: ручная и хрупкая
  • Luxon: декларативная

Календарные операции

Luxon корректно обрабатывает сложные случаи календарной логики.

Добавление месяцев

DateTime.local(2026, 1, 31).plus({ months: 1 });

Результат автоматически корректируется с учётом длины месяца.

Начало и конец единиц времени

const dt = DateTime.now();

dt.startOf("day");
dt.endOf("month");

Локализация

Luxon поддерживает локали на уровне форматирования.

DateTime.now()
  .setLocale("fr")
  .toLocaleString(DateTime.DATE_FULL);

Локализация влияет на:

  • названия месяцев
  • порядок компонентов даты
  • формат представления времени

Взаимодействие с JavaScript Date

Luxon не заменяет Date полностью, а интегрируется с ним.

Конвертация в Date

const jsDate = DateTime.now().toJSDate();

Создание из Date

const dt = DateTime.fromJSDate(new Date());

Работа с часовыми поясами в серверной среде

В серверных приложениях критично фиксировать временную зону:

const dt = DateTime.utc().setZone("Asia/Almaty");

Или полностью работать в UTC:

const dt = DateTime.utc();

Это устраняет расхождения между средами выполнения.


Сериализация и хранение данных

Luxon предоставляет безопасные способы хранения дат.

ISO как стандарт

const serialized = DateTime.now().toISO();

Восстановление

const restored = DateTime.fromISO(serialized);

Обработка ошибок парсинга

При некорректных данных Luxon возвращает объект с флагом валидности:

const dt = DateTime.fromISO("invalid");

dt.isValid; // false
dt.invalidReason;

Итоговая модель работы с временем

Использование Luxon формирует устойчивую модель:

  • DateTime — точка во времени
  • Duration — количество времени
  • Interval — диапазон времени
  • Time zone — обязательная часть модели

Такой подход устраняет неоднозначности, характерные для встроенного Date, и делает работу с датой детерминированной в распределённых системах, клиент-серверных архитектурах и многозонных приложениях.