Примеры сложных форматов

Работа с датами в Luxon становится особенно важной при обработке данных, поступающих из разных источников, где форматы времени часто не совпадают. Реальные приложения сталкиваются с ISO-строками с часовыми поясами, HTTP-датами, SQL-таймстампами и пользовательскими форматами, требующими строгого разбора и нормализации.

ISO 8601 в практике редко встречается в «идеальном» виде. Чаще используются расширенные формы с миллисекундами, смещениями и отсутствующими компонентами.

import { DateTime } from "luxon";

const a = DateTime.fromISO("2026-05-23T14:45:30.123+06:00");
const b = DateTime.fromISO("2026-05-23T14:45:30Z");
const c = DateTime.fromISO("2026-05-23T14:45");

Luxon корректно интерпретирует отсутствие секунд или миллисекунд, автоматически подставляя нули. При наличии зоны времени создаётся объект с учётом смещения, а при Z — с привязкой к UTC.

Особенность обработки состоит в том, что ISO-строки допускают вариативность:

  • отсутствие секунд
  • отсутствие миллисекунд
  • наличие или отсутствие часового пояса
  • смещение +hh:mm или -hh:mm

При этом результат всегда приводится к внутреннему представлению DateTime, где можно явно управлять зоной.

RFC 2822 и HTTP-даты

Форматы, используемые в email и HTTP-заголовках, имеют собственную специфику.

const rfc = DateTime.fromRFC2822("Tue, 23 May 2026 14:45:30 +0600");
const http = DateTime.fromHTTP("Tue, 23 May 2026 08:45:30 GMT");

Особенность этих форматов заключается в:

  • наличии текстового представления дня недели
  • фиксированных правил написания месяца
  • смещениях без двоеточия (+0600 вместо +06:00)

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

SQL-подобные временные строки

Базы данных часто возвращают даты в формате YYYY-MM-DD HH:mm:ss, который не является строго ISO.

const sql = DateTime.fromSQL("2026-05-23 14:45:30");
const sqlWithZone = DateTime.fromSQL("2026-05-23 14:45:30+06:00");

SQL-форматы удобны тем, что:

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

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

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

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

const dt = DateTime.fromFormat(
  "23/05/2026 14-45-30",
  "dd/MM/yyyy HH-mm-ss"
);

Система токенов Luxon позволяет описывать практически любые комбинации:

  • dd, MM, yyyy — календарные компоненты
  • HH, mm, ss — время
  • ZZ — смещение
  • ccc, cccc — дни недели
  • LLL, LLLL — месяцы в текстовом виде

Сложность возникает при неоднозначных форматах:

const ambiguous = DateTime.fromFormat("05-06-2026", "MM-dd-yyyy");

Такие строки могут интерпретироваться по-разному в зависимости от соглашений локали, поэтому важна явная фиксация шаблона.

Обработка временных зон и смещений

Сложные форматы часто включают комбинации локального времени и зонального смещения.

const dt1 = DateTime.fromISO("2026-05-23T14:45:30+06:00");
const dt2 = dt1.setZone("UTC");
const dt3 = dt1.setZone("Europe/Paris");

Здесь происходит не изменение момента времени, а перерасчёт отображения:

  • исходное время фиксирует абсолютный момент
  • смена зоны изменяет представление
  • смещение пересчитывается автоматически

Особенно важно при работе с логами и распределёнными системами, где один и тот же момент может отображаться в разных часовых поясах.

Нестандартные форматы с отсутствующими компонентами

В реальных данных часто отсутствуют части даты:

const partial1 = DateTime.fromFormat("2026-05", "yyyy-MM");
const partial2 = DateTime.fromFormat("14:45", "HH:mm");

Luxon заполняет недостающие поля минимальными значениями:

  • день → 1
  • время → 00:00:00

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

Форматирование сложных представлений

После разбора часто требуется вывести данные в специфическом формате.

const dt = DateTime.fromISO("2026-05-23T14:45:30+06:00");

const f1 = dt.toFormat("dd LLL yyyy HH:mm");
const f2 = dt.toFormat("cccc, dd LLLL yyyy");
const f3 = dt.toFormat("HH:mm ZZZZ");

Возможные сложности:

  • различие локалей при выводе текстовых месяцев
  • форматирование смещений (ZZZ, ZZZZ)
  • недельные дни (cccc)
  • порядковые числа (ordinal)

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

При работе с мультиязычными интерфейсами важна привязка к локали:

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

const formatted = dt.toLocaleString({
  weekday: "long",
  year: "numeric",
  month: "long",
  day: "2-digit"
});

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

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

Длительности и сложные представления времени

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

import { Duration } from "luxon";

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

const normalized = d.normalize();
const formatted = d.toFormat("d 'days' h 'hours' m 'minutes'");

Особенность заключается в необходимости нормализации:

  • 90 минут → 1 час 30 минут
  • 25 часов → 1 день 1 час

Интервалы и пересечения временных диапазонов

Сложные форматы часто включают работу с диапазонами дат.

import { Interval } from "luxon";

const start = DateTime.fromISO("2026-05-23T10:00:00");
const end = DateTime.fromISO("2026-05-23T18:00:00");

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

Операции над интервалами:

const shifted = interval.mapEndpoints(dt => dt.plus({ hours: 1 }));
const overlaps = interval.overlaps(anotherInterval);

Использование интервалов особенно важно при планировании событий и обработке расписаний.

Разбор нестандартных и ошибочных форматов

Сложные форматы неизбежно включают ошибки в данных.

const invalid = DateTime.fromISO("2026-13-40T99:99:99");

Luxon помечает такие значения как невалидные:

invalid.isValid; // false
invalid.invalidReason;
invalid.invalidExplanation;

Это позволяет отделять корректные данные от повреждённых без исключений в рантайме.

Комбинированные сценарии преобразований

Реальные задачи часто включают цепочки преобразований:

const raw = "23/05/2026 14-45";

const parsed = DateTime.fromFormat(raw, "dd/MM/yyyy HH-mm", {
  zone: "Asia/Almaty"
});

const utc = parsed.toUTC();
const output = utc.toISO();

Здесь происходит последовательная трансформация:

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

Такие цепочки формируют основу работы с временными данными в распределённых системах, где согласованность форматов критична.