eachWeekOfInterval и eachMonthOfInterval

Функция eachWeekOfInterval из библиотеки date-fns формирует массив дат, соответствующих началу каждой недели внутри заданного временного интервала. Поведение функции определяется локалью (первый день недели) и правилами округления границ интервала.

Сигнатура

eachWeekOfInterval(interval, options?)

Параметры

interval

{
  start: Date | number,
  end: Date | number
}
  • start — начало интервала
  • end — конец интервала

options (необязательный параметр)

{
  locale?: Locale,
  weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6
}
  • weekStartsOn — задаёт первый день недели (0 — воскресенье, 1 — понедельник и т.д.)
  • locale — локаль, определяющая правила календарной недели

Поведение функции

Функция:

  • определяет первую неделю, пересекающую start
  • находит каждую последующую неделю с шагом 7 дней
  • возвращает массив дат, каждая из которых является началом недели согласно настройкам
  • включает недели, которые частично пересекаются с интервалом

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


Пример базового использования

import { eachWeekOfInterval } from 'date-fns'

const result = eachWeekOfInterval({
  start: new Date(2024, 0, 1),
  end: new Date(2024, 0, 31)
})

console.log(result)

Результат:

[
  2023-12-31,
  2024-01-07,
  2024-01-14,
  2024-01-21,
  2024-01-28
]

(даты могут отличаться в зависимости от weekStartsOn и локали)


Пример с изменением начала недели

import { eachWeekOfInterval } from 'date-fns'

const result = eachWeekOfInterval(
  {
    start: new Date(2024, 0, 1),
    end: new Date(2024, 0, 31)
  },
  {
    weekStartsOn: 1
  }
)

При weekStartsOn: 1 (понедельник) недели будут смещены, и массив начнётся с ближайшего понедельника.


Логика включения границ интервала

Если start попадает внутрь недели, функция возвращает начало этой недели, а не сам start.

Если end находится внутри недели, последняя неделя всё равно будет включена, поскольку она пересекает интервал.


Практические сценарии использования

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

Особенности и тонкости

  • функция не мутирует входные данные
  • результат всегда отсортирован по возрастанию
  • временная зона учитывается через стандартное поведение Date
  • при больших интервалах количество элементов растёт линейно

Типичные ошибки

  • ожидание включения только полных недель
  • игнорирование weekStartsOn, приводящее к смещению календаря
  • использование функции для дневных интервалов (не предназначена)

eachMonthOfInterval

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


Сигнатура

eachMonthOfInterval(interval)

Параметры

{
  start: Date | number,
  end: Date | number
}

Поведение функции

Алгоритм работы:

  • определяется месяц, в котором находится start
  • формируется дата первого дня этого месяца
  • последовательно добавляются первые дни следующих месяцев
  • процесс продолжается до месяца, содержащего end

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


Пример использования

import { eachMonthOfInterval } from 'date-fns'

const result = eachMonthOfInterval({
  start: new Date(2024, 0, 15),
  end: new Date(2024, 5, 10)
})

console.log(result)

Результат:

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

Особенности включения границ

Даже если start установлен в середине месяца, возвращается первый день этого месяца.

Если end находится внутри месяца, этот месяц включается полностью как последний элемент.


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

import { eachMonthOfInterval } from 'date-fns'

const months = eachMonthOfInterval({
  start: new Date(2023, 8, 10),
  end: new Date(2024, 2, 1)
})

Результат:

[
  2023-09-01,
  2023-10-01,
  2023-11-01,
  2023-12-01,
  2024-01-01,
  2024-02-01,
  2024-03-01
]

Применение в прикладных задачах

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

Особенности реализации

  • всегда возвращаются даты с числом 01
  • время устанавливается в начало суток
  • не зависит от локали
  • интервал обрабатывается по григорианскому календарю

Частые ошибки

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

Сравнение eachWeekOfInterval и eachMonthOfInterval

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

eachWeekOfInterval

  • шаг: 7 дней
  • опора: начало недели
  • зависит от локали
  • используется для коротких периодов

eachMonthOfInterval

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

Общий принцип

Обе функции выполняют одну и ту же концепцию:

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

Различие заключается только в единице дискретизации — неделя или месяц.