Временные диапазоны

Day.js представляет собой компактную библиотеку для работы с датами, ориентированную на неизменяемость объектов и совместимость с привычным API Moment.js. В контексте временных диапазонов Day.js предоставляет базовые средства манипуляции датами, а более сложные операции строятся через плагины и комбинацию методов сравнения, смещения и вычисления разницы.

Временной диапазон в Day.js обычно моделируется парой значений:

  • начало интервала (start)
  • конец интервала (end)

Каждое значение является экземпляром Day.js, а сам диапазон — логической конструкцией, не встроенной в ядро библиотеки.

const start = dayjs('2026-01-01');
const end = dayjs('2026-01-10');

Ключевое свойство: неизменяемость. Любая операция над датой возвращает новый объект, что упрощает построение цепочек преобразований диапазонов.

Нормализация границ диапазона

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

const start = dayjs('2026-01-01').startOf('day');
const end = dayjs('2026-01-10').endOf('day');

Методы:

  • startOf('unit') — установка начала единицы времени
  • endOf('unit') — установка конца единицы времени

Единицы могут включать day, month, year, hour, minute, second.

Сравнение дат внутри диапазона

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

  • isBefore
  • isAfter
  • isSame
const d = dayjs('2026-01-05');

const inRange =
  d.isAfter(start) &&
  d.isBefore(end);

Поведение сравнения строгое: границы по умолчанию не включаются.

Включение границ диапазона

Для включающих сравнений применяется параметр единицы времени или явная логика:

const inRangeInclusive =
  (d.isAfter(start) || d.isSame(start)) &&
  (d.isBefore(end) || d.isSame(end));

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

Проверка принадлежности через isBetween

Плагин isBetween расширяет Day.js специализированным методом проверки попадания в интервал.

Подключение:

import isBetween from 'dayjs/plugin/isBetween';
dayjs.extend(isBetween);

Использование:

const d = dayjs('2026-01-05');

d.isBetween(start, end);

Метод поддерживает режимы включительности границ:

d.isBetween(start, end, null, '[)');
d.isBetween(start, end, 'day', '[]');

Обозначения:

  • () — исключающие границы
  • [] — включающие границы
  • [) — включение слева
  • () — исключение справа

Пересечение временных диапазонов

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

Пусть заданы диапазоны A и B:

const A_start = dayjs('2026-01-01');
const A_end = dayjs('2026-01-10');

const B_start = dayjs('2026-01-05');
const B_end = dayjs('2026-01-15');

Условие пересечения:

const intersects =
  A_start.isBefore(B_end) &&
  B_start.isBefore(A_end);

Логика основана на проверке взаимного перекрытия интервалов.

Вычисление длительности диапазона

Разница между концом и началом диапазона вычисляется через diff:

const durationDays = end.diff(start, 'day');

Поддерживаются единицы:

  • millisecond
  • second
  • minute
  • hour
  • day
  • month
  • year

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

Итерация по временным диапазонам

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

Пример обхода по дням:

let cursor = start;

while (cursor.isBefore(end) || cursor.isSame(end)) {
  cursor = cursor.add(1, 'day');
}

Аналогично возможны шаги:

  • по неделям
  • по месяцам
  • по часам
cursor.add(1, 'month');
cursor.add(6, 'hour');

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

Сдвиг диапазона

Смещение всего интервала выполняется через add и subtract:

const shiftedStart = start.add(7, 'day');
const shiftedEnd = end.add(7, 'day');

Диапазон сохраняет длительность, изменяя только положение на временной оси.

Обратное смещение:

const previousStart = start.subtract(1, 'month');
const previousEnd = end.subtract(1, 'month');

Выравнивание диапазонов по календарным единицам

Часто требуется привести диапазон к календарным границам:

const monthRangeStart = dayjs('2026-03-15').startOf('month');
const monthRangeEnd = dayjs('2026-03-15').endOf('month');

Такая нормализация используется при построении отчетов по периодам:

  • месяц
  • квартал
  • год

Открытые и закрытые интервалы

Временные диапазоны различаются по включённости границ:

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

Логика выражается через комбинацию isBefore, isAfter, isSame или isBetween.

Полуоткрытый интервал [start, end) часто используется в вычислениях для исключения дублирования крайних точек.

Сравнение диапазонов по положению

Для определения взаимного положения диапазонов применяются условия:

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

A_end.isBefore(B_start);

Полное следование

A_start.isAfter(B_end);

Частичное перекрытие

A_start.isBefore(B_end) && A_end.isAfter(B_start);

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

Приведение дат к общей временной зоне

При работе с диапазонами критично учитывать временную зону. Подключение UTC-режима:

import utc from 'dayjs/plugin/utc';
dayjs.extend(utc);

Использование:

const d = dayjs.utc('2026-01-01');

Для сложных сценариев применяется плагин временных зон:

import timezone from 'dayjs/plugin/timezone';
dayjs.extend(timezone);

Разбиение диапазона на сегменты

Диапазон может быть разложен на поддиапазоны фиксированной длины:

const segments = [];

let cursor = start;

while (cursor.isBefore(end)) {
  const next = cursor.add(3, 'day');
  segments.push({ start: cursor, end: next });
  cursor = next;
}

Такой подход используется при:

  • батчевой обработке данных
  • разбиении отчетных периодов
  • генерации графиков

Преобразование диапазона в календарные окна

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

const weekStart = dayjs('2026-05-23').startOf('week');
const weekEnd = dayjs('2026-05-23').endOf('week');

Аналогично:

  • месяц → startOf('month')
  • год → startOf('year')

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

Корректный диапазон удовлетворяет условию:

start.isBefore(end) || start.isSame(end)

Обратное состояние трактуется как инвертированный интервал, требующий нормализации:

const normalizedStart = start.isAfter(end) ? end : start;
const normalizedEnd = start.isAfter(end) ? start : end;

Инкрементальная работа с диапазонами

При потоковой обработке временных данных диапазон используется как скользящее окно:

const windowSize = 10;

let windowStart = start;
let windowEnd = start.add(windowSize, 'day');

while (windowEnd.isBefore(end)) {
  windowStart = windowStart.add(1, 'day');
  windowEnd = windowEnd.add(1, 'day');
}

Такая модель характерна для:

  • временных окон аналитики
  • скользящих средних
  • мониторинга событий

Преобразование диапазонов в метрики

Диапазоны часто служат основой для вычисления производных показателей:

const days = end.diff(start, 'day');
const hours = end.diff(start, 'hour');
const minutes = end.diff(start, 'minute');

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