Разбиение интервалов на периоды: eachDayOfInterval

Работа с временными интервалами в date-fns строится вокруг принципа неизменяемости и композиции функций. Интервалы представляют собой диапазоны между двумя датами, где каждая операция над диапазоном возвращает новый результат без модификации исходных данных. Одной из базовых операций разбиения интервала на дискретные значения является eachDayOfInterval.


Функция eachDayOfInterval формирует последовательность дат, покрывающих весь указанный диапазон с шагом в один день. Интервал задаётся двумя границами: начальной и конечной датой. Результатом становится массив объектов Date, включающий каждую календарную дату внутри диапазона.

Сигнатура

eachDayOfInterval({ start, end })

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

Функция принимает объект с двумя обязательными свойствами:

start

Начальная дата интервала.

end

Конечная дата интервала.

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


Базовый принцип работы

Алгоритм построен на последовательном увеличении даты от start до end с шагом в один календарный день. При этом учитывается календарная арифметика, а не фиксированное количество миллисекунд, что позволяет корректно обрабатывать переходы через месяцы и годы.


Пример генерации последовательности дней

import { eachDayOfInterval } from 'date-fns';

const result = eachDayOfInterval({
  start: new Date(2026, 0, 1),
  end: new Date(2026, 0, 5),
});

console.log(result);

Результат:

[
  2026-01-01,
  2026-01-02,
  2026-01-03,
  2026-01-04,
  2026-01-05
]

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


Инклюзивность границ интервала

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

  • начальная дата входит в результат
  • конечная дата входит в результат

Это поведение важно учитывать при расчётах длины интервала.


Работа с обратным порядком дат

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

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

const interval = {
  start: new Date(2026, 0, 10),
  end: new Date(2026, 0, 1),
};

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


Использование с динамическими диапазонами

Генерация дней месяца

import { eachDayOfInterval, endOfMonth } from 'date-fns';

const start = new Date(2026, 0, 1);
const end = endOfMonth(start);

const days = eachDayOfInterval({ start, end });

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


Формирование календарных сеток

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

Типичная структура данных:

  • массив всех дней месяца
  • последующая группировка по неделям
  • отображение в виде сетки 7×N

Комбинирование с фильтрацией

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

Пример исключения выходных дней

import { eachDayOfInterval, isWeekend } from 'date-fns';

const days = eachDayOfInterval({
  start: new Date(2026, 0, 1),
  end: new Date(2026, 0, 31),
});

const weekdays = days.filter(date => !isWeekend(date));

Применение в расчёте рабочих периодов

При моделировании рабочих графиков функция используется как базовый генератор временной оси. Далее на неё накладываются правила:

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

Обработка часовых поясов

eachDayOfInterval работает с объектами Date, где календарная часть определяется локальной временной зоной среды выполнения. Это означает:

  • переходы через полночь зависят от локального времени
  • при смене часового пояса возможны сдвиги интерпретации даты

Для серверных приложений это особенно важно при унификации времени хранения и отображения.


Поведение при переходе через месяцы и годы

Функция корректно обрабатывает:

  • смену месяцев с разным количеством дней
  • високосные годы
  • переходы декабрь → январь

Пример:

eachDayOfInterval({
  start: new Date(2024, 11, 30),
  end: new Date(2025, 0, 2),
});

Результат охватывает непрерывную последовательность без пропусков.


Внутренний принцип инкремента

Каждый следующий элемент вычисляется как:

  • текущая дата + 1 календарный день

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


Типичные сценарии применения

Построение временных рядов

Используется для подготовки оси времени в аналитике:

  • ежедневные продажи
  • активность пользователей
  • логирование событий

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

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

  • загрузка данных по дням
  • агрегация статистики

Календарные представления

Формирование структуры дней для UI:

  • месячные календари
  • планировщики задач
  • расписания

Ошибки и ограничения

Некорректные даты

При передаче некорректных значений Date возможны:

  • Invalid Date в результате
  • непредсказуемое поведение интервалов

Пустой интервал

Если start и end совпадают, результат содержит один элемент.


Связанные функции для расширения логики

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

  • addDays — ручное смещение дат
  • differenceInDays — вычисление длины интервала
  • startOfDay — нормализация времени
  • endOfDay — фиксация границы суток

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


Масштабирование на большие диапазоны

При работе с длинными интервалами (несколько лет) важно учитывать:

  • рост размера массива
  • нагрузку на память
  • необходимость ленивой генерации (через итераторы или генераторы)

Стандартная реализация возвращает полный массив, что подходит для ограниченных диапазонов и UI-задач, но требует осторожности в аналитических системах с большими данными.