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

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

Объект Interval в Luxon описывает промежуток времени между двумя моментами — началом и концом. Базовое строковое представление формируется через метод toString():

import { DateTime, Interval } from "luxon";

const start = DateTime.local(2026, 1, 1, 10, 0);
const end = DateTime.local(2026, 1, 1, 12, 30);

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

console.log(interval.toString());
// [2026-01-01T10:00:00.000+06:00 – 2026-01-01T12:30:00.000+06:00]

Такое представление предназначено в первую очередь для отладки: оно содержит ISO-представления границ интервала и не подходит для пользовательского интерфейса.


ISO-формат интервала

Наиболее важный способ сериализации — метод toISO(), который возвращает стандарт ISO 8601 Interval:

interval.toISO();
// "2026-01-01T10:00:00.000+06:00/2026-01-01T12:30:00.000+06:00"

Символ / разделяет начало и конец интервала. Это универсальный формат, поддерживаемый многими системами обмена датами.

Варианты вывода ISO

Метод toISO() принимает опции:

interval.toISO({ suppressMilliseconds: true });
// "2026-01-01T10:00:00+06:00/2026-01-01T12:30:00+06:00"
interval.toISO({ includeOffset: false });
// "2026-01-01T04:00:00.000Z/2026-01-01T06:30:00.000Z"

Параметры влияют на детализацию времени и способ отображения часового пояса, но структура интервала остаётся неизменной.


Локализованное представление интервала

Для человекочитаемого вывода используется toLocaleString(). Он форматирует границы интервала с учётом локали и заданных форматов DateTime:

import { DateTime, Interval } from "luxon";

const start = DateTime.local(2026, 5, 1, 9);
const end = DateTime.local(2026, 5, 1, 18);

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

interval.toLocaleString(DateTime.DATETIME_MED);
// "1 мая 2026 г., 09:00 – 1 мая 2026 г., 18:00"

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


Форматирование через преобразование границ

Interval не имеет универсального метода toFormat, как DateTime, поэтому кастомное форматирование реализуется через ручное преобразование начальной и конечной точек:

interval.start.toFormat("dd.MM.yyyy HH:mm") +
" - " +
interval.end.toFormat("dd.MM.yyyy HH:mm");

Результат:

01.05.2026 09:00 - 01.05.2026 18:00

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


Формирование строк через ISO-границы

Часто используется комбинированный подход, когда обе границы форматируются одинаково:

const format = "yyyy LLL dd, HH:mm";

`${interval.start.toFormat(format)} → ${interval.end.toFormat(format)}`;

Этот способ позволяет унифицировать представление интервалов в интерфейсах расписаний и календарей.


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

Интервал можно преобразовать в Duration, что открывает доступ к форматированию длительности:

const duration = interval.toDuration(["hours", "minutes"]);
duration.toHuman();
// "2 hours, 30 minutes"

Это не форматирование самого интервала, но способ выразить его смысловую характеристику. Такой подход используется там, где важна не привязка ко времени, а длина промежутка.


Особенности форматирования границ

Форматирование интервала всегда зависит от двух независимых DateTime:

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

Пример с разными зонами:

const start = DateTime.fromISO("2026-01-01T10:00", { zone: "utc" });
const end = DateTime.fromISO("2026-01-01T15:00", { zone: "Europe/Berlin" });

Interval.fromDateTimes(start, end).toString();

В таких случаях строковое представление сохраняет оба контекста без приведения к единой зоне.


Контроль читаемости интервала

Для интерфейсов обычно применяются правила упрощения отображения:

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

Пример ручной реализации:

function formatInterval(i) {
  const sameDay = i.start.hasSame(i.end, "day");

  if (sameDay) {
    return `${i.start.toFormat("HH:mm")}–${i.end.toFormat("HH:mm")}`;
  }

  return `${i.start.toFormat("dd.MM HH:mm")}–${i.end.toFormat("dd.MM HH:mm")}`;
}

Такой подход имитирует поведение календарных приложений.


Сериализация и восстановление

ISO-формат, полученный через toISO(), используется для хранения и передачи:

const serialized = interval.toISO();

const restored = Interval.fromISO(serialized);

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


Сравнение способов форматирования

  • toString() — техническое представление для отладки
  • toISO() — стандартный обменный формат
  • toLocaleString() — локализованный пользовательский вывод
  • DateTime.toFormat() на границах — полный контроль над стилем
  • toDuration() — преобразование в длительность для смыслового отображения