Генерация последовательностей дат

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


В Date-fns последовательности дат строятся вокруг структуры интервала:

{
  start: Date,
  end: Date
}

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


Генерация последовательности по дням

Основной инструмент для ежедневных последовательностей — eachDayOfInterval.

import { eachDayOfInterval } from 'date-fns';

const range = eachDayOfInterval({
  start: new Date(2024, 0, 1),
  end: new Date(2024, 0, 7)
});

console.log(range);

Результатом становится массив:

[
  2024-01-01,
  2024-01-02,
  2024-01-03,
  2024-01-04,
  2024-01-05,
  2024-01-06,
  2024-01-07
]

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


Генерация недельных последовательностей

Для работы с неделями используется eachWeekOfInterval.

import { eachWeekOfInterval } from 'date-fns';

const weeks = eachWeekOfInterval({
  start: new Date(2024, 0, 1),
  end: new Date(2024, 2, 1)
});

По умолчанию каждая неделя начинается с воскресенья (или локально настроенного дня недели при использовании дополнительных опций через startOfWeek).

Результат — массив дат, соответствующих началу каждой недели в интервале.


Месячные последовательности

Для генерации по месяцам применяется eachMonthOfInterval.

import { eachMonthOfInterval } from 'date-fns';

const months = eachMonthOfInterval({
  start: new Date(2023, 0, 1),
  end: new Date(2023, 11, 31)
});

Каждый элемент массива соответствует первому дню месяца внутри диапазона.

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

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

Годовые последовательности

Функция eachYearOfInterval формирует список годов:

import { eachYearOfInterval } from 'date-fns';

const years = eachYearOfInterval({
  start: new Date(2018, 0, 1),
  end: new Date(2024, 0, 1)
});

Возвращаемые значения нормализуются к 1 января каждого года.


Ручная генерация последовательностей

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

Пример: шаг в 3 дня

import { addDays } from 'date-fns';

const start = new Date(2024, 0, 1);
const end = new Date(2024, 0, 15);

const result = [];

let current = start;

while (current <= end) {
  result.push(current);
  current = addDays(current, 3);
}

Подобный подход применяется для:

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

Генерация с нормализацией границ

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

import { startOfDay, endOfDay } from 'date-fns';

const interval = {
  start: startOfDay(new Date(2024, 0, 1)),
  end: endOfDay(new Date(2024, 0, 7))
};

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


Преобразование последовательностей

Сгенерированные массивы часто трансформируются с использованием format.

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

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

const formatted = days.map(date =>
  format(date, 'yyyy-MM-dd')
);

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

  • вывода в UI
  • сериализации
  • построения API-ответов

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

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

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

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

const weekdays = days.filter(date => {
  const day = getDay(date);
  return day !== 0 && day !== 6;
});

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


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

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

Алгоритм обычно включает:

  1. определение начала месяца
  2. расширение до начала недели
  3. генерацию полного диапазона отображения
import {
  startOfMonth,
  endOfMonth,
  startOfWeek,
  endOfWeek,
  eachDayOfInterval
} from 'date-fns';

const monthStart = startOfMonth(new Date(2024, 0, 1));
const monthEnd = endOfMonth(monthStart);

const calendarStart = startOfWeek(monthStart);
const calendarEnd = endOfWeek(monthEnd);

const calendarDays = eachDayOfInterval({
  start: calendarStart,
  end: calendarEnd
});

Результат — полный набор дат для отрисовки сетки месяца.


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

Date-fns часто используется для подготовки данных под графики.

Пример генерации точек наблюдения:

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

const data = eachDayOfInterval({
  start: new Date(2024, 0, 1),
  end: new Date(2024, 0, 10)
}).map(date => ({
  date: format(date, 'yyyy-MM-dd'),
  value: Math.random()
}));

Такая структура применяется в аналитике и визуализации.


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

При генерации больших диапазонов важно учитывать:

  • линейную сложность O(n)
  • рост потребления памяти при хранении массивов
  • отсутствие ленивых итераторов в базовых функциях Date-fns

Для диапазонов в десятки тысяч элементов предпочтительнее:

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

Работа с временными смещениями

При пересечении часовых поясов могут возникать эффекты сдвига даты. Date-fns оперирует объектами Date, поэтому корректность зависит от локального окружения.

Типичная практика — нормализация через начало дня:

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

const days = eachDayOfInterval({
  start: startOfDay(new Date(2024, 0, 1)),
  end: startOfDay(new Date(2024, 0, 10))
});

Расширенные паттерны генерации

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

  • группировка по неделям после eachDayOfInterval
  • построение месячных бакетов
  • агрегация событий по датам
import { eachDayOfInterval, format } from 'date-fns';

const grouped = eachDayOfInterval({
  start: new Date(2024, 0, 1),
  end: new Date(2024, 0, 31)
}).reduce((acc, date) => {
  const key = format(date, 'yyyy-MM');
  acc[key] = (acc[key] || 0) + 1;
  return acc;
}, {});

Унификация подходов

Генерация последовательностей в Date-fns строится вокруг единого принципа:

  • вход: интервал дат
  • выход: массив нормализованных дат
  • трансформация: через стандартные функции библиотеки

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