Недостающие функции

Объект Date в JavaScript долгое время оставался единственным встроенным инструментом для работы с датой и временем. Несмотря на широкое распространение, у него накопилось множество ограничений:

  • неудобный API;
  • мутирующие методы;
  • сложная работа с часовыми поясами;
  • путаница между локальным временем и UTC;
  • нестабильный парсинг строк;
  • отсутствие встроенной локализации;
  • неудобное форматирование;
  • сложные вычисления интервалов.

Luxon был создан как современная замена устаревшим подходам. Библиотека предоставляет выразительный, безопасный и предсказуемый API для работы со временем.


Какие проблемы решает Luxon

Иммутабельность

Объекты Luxon не изменяются после создания.

В стандартном Date многие методы мутируют объект:

const date = new Date();

date.setHours(15);

console.log(date);

В Luxon изменения создают новый экземпляр:

import { DateTime } from "luxon";

const now = DateTime.now();

const upd ated = now.se t({ hour: 15 });

console.log(now.toString());
console.log(updated.toString());

Это устраняет большое количество ошибок, связанных с неожиданным изменением состояния.


Безопасный парсинг дат

Проблемы Date.parse

Поведение стандартного парсинга отличается между браузерами.

new Date("01.02.2025");

Некоторые среды интерпретируют строку как:

  • 1 февраля;
  • 2 января;
  • invalid date.

Luxon требует явного формата.

const dt = DateTime.fromFormat(
  "01.02.2025",
  "dd.MM.yyyy"
);

console.log(dt.toISO());

Проверка валидности

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

const dt = DateTime.fromFormat(
  "99.99.2025",
  "dd.MM.yyyy"
);

console.log(dt.isValid);
console.log(dt.invalidReason);

Результат:

false
unit out of range

Работа с часовыми поясами

Основная проблема JavaScript

Стандартный Date хранит время в UTC, но отображает его в локальном часовом поясе среды выполнения.

Это создаёт путаницу:

const date = new Date();

console.log(date);
console.log(date.toISOString());

Luxon делает работу с зонами явной.


Создание даты с зоной

const dt = DateTime.now().setZone("Europe/Moscow");

console.log(dt.toString());

Смена часового пояса

const local = DateTime.now();

const tokyo = local.setZone("Asia/Tokyo");

console.log(local.toString());
console.log(tokyo.toString());

Сохранение локального времени

По умолчанию Luxon преобразует момент времени.

Иногда требуется сохранить локальные часы:

const dt = DateTime.fromISO(
  "2025-05-10T12:00",
  { zone: "Europe/Moscow" }
);

const result = dt.setZone(
  "Asia/Tokyo",
  { keepLocalTime: true }
);

console.log(result.toString());

Работа с UTC

Создание UTC-времени

const utc = DateTime.utc();

console.log(utc.toISO());

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

const local = DateTime.now();

const utc = local.toUTC();

console.log(local.toString());
console.log(utc.toString());

Удобное форматирование

Недостатки toLocaleString

Стандартное форматирование сложно читать и поддерживать.

date.toLocaleString("ru", {
  year: "numeric",
  month: "long",
  day: "numeric"
});

Luxon предлагает компактный API.


Форматирование через шаблоны

const dt = DateTime.now();

console.log(
  dt.toFormat("dd.MM.yyyy")
);

console.log(
  dt.toFormat("HH:mm:ss")
);

Полный набор токенов

Токен Значение
yyyy год
MM месяц
dd день
HH часы
mm минуты
ss секунды
cccc день недели
LLLL название месяца

Пример:

const dt = DateTime.now();

console.log(
  dt.toFormat("cccc, dd LLLL yyyy")
);

Локализация

Установка локали

const dt = DateTime.now()
  .setLocale("ru");

console.log(
  dt.toFormat("cccc")
);

Разные языки

const dt = DateTime.now();

console.log(
  dt.setLocale("en").toFormat("LLLL")
);

console.log(
  dt.setLocale("fr").toFormat("LLLL")
);

console.log(
  dt.setLocale("de").toFormat("LLLL")
);

Вычисления с датами

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

const dt = DateTime.now();

const future = dt.plus({
  days: 10,
  hours: 5
});

console.log(future.toString());

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

const dt = DateTime.now();

const past = dt.minus({
  weeks: 2
});

console.log(past.toString());

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

Начало дня

const dt = DateTime.now();

console.log(
  dt.startOf("day").toString()
);

Конец месяца

const dt = DateTime.now();

console.log(
  dt.endOf("month").toString()
);

Популярные единицы

year
quarter
month
week
day
hour
minute
second

Сравнение дат

Проверка равенства

const a = DateTime.now();
const b = a.plus({ minutes: 1 });

console.log(a.equals(b));

Сравнение через timestamp

console.log(a.toMillis());
console.log(b.toMillis());

console.log(a < b);

Интервалы времени

Объект Interval

Luxon содержит встроенный тип интервалов.

import { Interval } from "luxon";

const start = DateTime.now();

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

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

console.log(interval.length("days"));

Проверка попадания в диапазон

const now = DateTime.now();

console.log(
  interval.contains(now)
);

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

const a = Interval.fromDateTimes(
  DateTime.now(),
  DateTime.now().plus({ days: 10 })
);

const b = Interval.fromDateTimes(
  DateTime.now().plus({ days: 5 }),
  DateTime.now().plus({ days: 15 })
);

console.log(a.overlaps(b));

Продолжительности

Объект Duration

Luxon умеет работать не только с моментами времени, но и с продолжительностями.

import { Duration } from "luxon";

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

console.log(duration.toISO());

Преобразование единиц

const duration = Duration.fromObject({
  minutes: 150
});

console.log(
  duration.as("hours")
);

Нормализация

const duration = Duration.fromObject({
  minutes: 90
}).normalize();

console.log(duration.toObject());

Результат:

{
  hours: 1,
  minutes: 30
}

Разница между датами

Метод diff

const start = DateTime.now();

const end = start.plus({
  days: 3,
  hours: 5
});

const diff = end.diff(start, [
  "days",
  "hours"
]);

console.log(diff.toObject());

Разница в миллисекундах

const diff = end.diff(start);

console.log(diff.toMillis());

Работа с ISO

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

Luxon ориентирован на ISO 8601.

Пример ISO-строки:

2025-05-10T14:30:00.000+03:00

Создание из ISO

const dt = DateTime.fromISO(
  "2025-05-10T14:30:00"
);

console.log(dt.toString());

Преобразование в ISO

const dt = DateTime.now();

console.log(dt.toISO());

RFC и HTTP-форматы

RFC 2822

const dt = DateTime.fromRFC2822(
  "Tue, 25 Nov 2025 13:30:00 +0300"
);

console.log(dt.toISO());

HTTP Date

const dt = DateTime.fromHTTP(
  "Sun, 06 Nov 1994 08:49:37 GMT"
);

console.log(dt.toISO());

Работа с Unix Timestamp

Создание из timestamp

const dt = DateTime.fromSeconds(
  1700000000
);

console.log(dt.toISO());

Timestamp в миллисекундах

const dt = DateTime.fromMillis(
  1700000000000
);

console.log(dt.toISO());

Получение timestamp

const dt = DateTime.now();

console.log(dt.toSeconds());
console.log(dt.toMillis());

Работа с календарными данными

День недели

const dt = DateTime.now();

console.log(dt.weekday);

Номер недели

console.log(dt.weekNumber);

День года

console.log(dt.ordinal);

Проверка високосного года

console.log(
  DateTime.now().isInLeapYear
);

Работа с массивами дат

Сортировка

const dates = [
  DateTime.now(),
  DateTime.now().minus({ days: 2 }),
  DateTime.now().plus({ days: 1 })
];

dates.sort(
  (a, b) => a.toMillis() - b.toMillis()
);

console.log(dates);

Генерация диапазонов

Последовательность дат

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

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

const days = interval.splitBy({
  days: 1
});

console.log(days);

Сериализация

Преобразование в JSON

const dt = DateTime.now();

console.log(
  JSON.stringify(dt)
);

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

const json = dt.toJSON();

const restored = DateTime.fromISO(json);

console.log(restored.toString());

Работа в Node.js

Использование таймзоны процесса

TZ=Europe/Moscow node app.js

Установка default zone

import { Settings } from "luxon";

Settings.defaultZone = "UTC";

Глобальная локаль

Settings.defaultLocale = "ru";

Проверка поддержки Intl

Luxon активно использует Intl.

Проверка:

console.log(
  typeof Intl !== "undefined"
);

Ошибки при работе с часовыми поясами

Неверная зона

const dt = DateTime.now().setZone(
  "Mars/Base"
);

console.log(dt.isValid);

Диагностика

console.log(dt.invalidReason);
console.log(dt.invalidExplanation);

Практический пример: логирование

function log(message) {
  const timestamp = DateTime.now()
    .toFormat("yyyy-MM-dd HH:mm:ss");

  console.log(
    `[${timestamp}] ${message}`
  );
}

log("Server started");

Практический пример: дедлайн

const deadline = DateTime.fromISO(
  "2025-12-31"
);

const now = DateTime.now();

const diff = deadline.diff(now, [
  "days",
  "hours"
]);

console.log(diff.toObject());

Практический пример: проверка просрочки

const expiresAt = DateTime.fromISO(
  "2025-01-01"
);

const expired =
  DateTime.now() > expiresAt;

console.log(expired);

Практический пример: календарь событий

const events = [
  {
    title: "Meeting",
    date: DateTime.fromISO(
      "2025-06-10T12:00"
    )
  },
  {
    title: "Conference",
    date: DateTime.fromISO(
      "2025-06-15T09:00"
    )
  }
];

events.forEach(event => {
  console.log(
    event.title,
    event.date.toFormat(
      "dd.MM.yyyy HH:mm"
    )
  );
});

Ограничения Luxon

Зависимость от Intl

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

  • старые браузеры;
  • устаревшие версии Node.js;
  • ограниченные embedded-системы.

Размер библиотеки

Luxon крупнее минималистичных решений вроде:

  • Day.js;
  • date-fns.

Нет полноценной timezone-базы внутри библиотеки

Luxon использует возможности среды выполнения.

Качество поддержки зон зависит от:

  • браузера;
  • версии Node.js;
  • ICU-данных системы.

Когда Luxon особенно полезен

Backend-приложения

  • API;
  • логирование;
  • cron-задачи;
  • дедлайны;
  • отчёты.

Frontend-приложения

  • календари;
  • расписания;
  • бронирование;
  • международные интерфейсы;
  • отображение локального времени.

Системы с несколькими часовыми поясами

  • международные сервисы;
  • SaaS-платформы;
  • системы аналитики;
  • финансовые приложения;
  • сервисы бронирования.