Метод divideEqually

В библиотеке Luxon отсутствует метод с названием divideEqually. В стандартном API нет функции, которая напрямую делит временной интервал на равные части с возвратом набора равномерно распределённых значений. При этом в Luxon присутствуют инструменты, позволяющие реализовать подобное поведение вручную через работу с Duration, DateTime и арифметикой временных значений.

В Luxon существует метод Duration#divide, который выполняет деление длительности на числовой коэффициент:

const { Duration } = require("luxon");

const d = Duration.fromObject({ hours: 10 });
const half = d.divide(2);

Результатом будет новая длительность, уменьшенная в два раза. Однако это не означает разбиение интервала на набор равных частей — метод возвращает только одну уменьшенную длительность.

Метод divideEqually в API отсутствует, поскольку библиотека не предоставляет встроенного механизма генерации массива интервалов или точек разбиения.

Реализация равномерного деления интервала через DateTime

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

Базовая идея строится на переводе интервала в миллисекунды:

const { DateTime } = require("luxon");

const start = DateTime.fromISO("2026-01-01T00:00:00");
const end = DateTime.fromISO("2026-01-02T00:00:00");

const totalMillis = end.toMillis() - start.toMillis();
const parts = 4;

const step = totalMillis / parts;

Далее каждая точка вычисляется добавлением шага:

const points = Array.from({ length: parts + 1 }, (_, i) =>
  DateTime.fromMillis(start.toMillis() + step * i)
);

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

Разбиение на равные интервалы (сегменты)

Если требуется получить именно интервалы, а не точки, используется смещение начальной границы:

const intervals = [];

for (let i = 0; i < parts; i++) {
  const segmentStart = DateTime.fromMillis(start.toMillis() + step * i);
  const segmentEnd = DateTime.fromMillis(start.toMillis() + step * (i + 1));

  intervals.push({
    start: segmentStart,
    end: segmentEnd
  });
}

Каждый элемент массива представляет собой независимый временной отрезок фиксированной длины.

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

При использовании DateTime важно учитывать, что арифметика через toMillis() переводит время в абсолютную шкалу UTC. Это устраняет проблемы с переходами часовых поясов и DST, но приводит к тому, что результат всегда выражен в абсолютных миллисекундах.

Альтернативный подход — использовать методы plus и diff:

const stepDuration = end.diff(start).as("milliseconds") / parts;

const points = [];
for (let i = 0; i <= parts; i++) {
  points.push(start.plus({ milliseconds: stepDuration * i }));
}

Этот вариант сохраняет семантику Luxon и лучше читается при работе в доменной логике времени.

Округление и накопление погрешности

При делении длительностей почти всегда возникает дробное значение миллисекунд. Это приводит к потенциальному накоплению ошибки при большом количестве сегментов.

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

const points = [];

for (let i = 0; i < parts; i++) {
  points.push(start.plus({ milliseconds: stepDuration * i }));
}

points.push(end);

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

Деление Duration как альтернативный подход

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

const { Duration } = require("luxon");

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

const step = duration.as("milliseconds") / parts;

const split = Array.from({ length: parts }, () =>
  Duration.fromMillis(step)
);

Однако такой подход теряет привязку к конкретным моментам времени и работает только с абстрактной длительностью.

Логическая модель отсутствия divideEqually

Отсутствие divideEqually объясняется архитектурным разделением ответственности:

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

Разбиение на равные части относится к прикладной логике, а не к базовой модели времени, поэтому реализуется на уровне пользовательского кода через комбинацию арифметики DateTime и Duration.