Получение номера недели: getWeek

Функция getWeek из библиотеки date-fns предназначена для вычисления номера недели в году для заданной даты. Она учитывает правила, по которым недели распределяются внутри календарного года, включая настройку первого дня недели и определения первой недели года. Это делает её гибким инструментом для работы с календарными системами, отличными от ISO-стандарта.


Базовая концепция нумерации недель

В разных системах календарей неделя может начинаться с разных дней (понедельник или воскресенье), а первая неделя года может определяться по различным правилам:

  • первая неделя содержит 1 января
  • первая неделя содержит определённое количество дней нового года (часто 4 дня)
  • используется ISO-стандарт (всегда понедельник и минимум 4 дня в году)

getWeek реализует настраиваемую модель, где поведение зависит от параметров options.


Сигнатура функции

getWeek(date, options)

Параметры:

  • date — дата, для которой вычисляется номер недели
  • options — объект конфигурации (необязательный)

Основные поля options:

{
  weekStartsOn: 0 | 1 | 2 | 3 | 4 | 5 | 6,
  firstWeekContainsDate: number
}

Параметр weekStartsOn

Определяет день, с которого начинается неделя:

Значение День недели
0 воскресенье
1 понедельник
2 вторник
6 суббота

Ключевая особенность: изменение этого параметра полностью влияет на разбиение календаря на недели.


Параметр firstWeekContainsDate

Определяет правило первой недели года. Значение — день января, который должен попасть в первую неделю года.

Примеры:

  • 1 — первая неделя содержит 1 января
  • 4 — первая неделя содержит минимум 4 дня нового года (часто используется в европейских системах)
  • 7 — первая неделя начинается только после первой полной недели

Базовое использование

import { getWeek } from 'date-fns'

getWeek(new Date(2024, 0, 1))

Результат зависит от настроек по умолчанию:

  • неделя начинается с воскресенья
  • первая неделя содержит 1 января

Пример с настройкой начала недели

import { getWeek } from 'date-fns'

const date = new Date(2024, 0, 10)

getWeek(date, { weekStartsOn: 1 })

В этом случае:

  • неделя начинается с понедельника
  • нумерация недель соответствует европейскому формату календаря

Пример с firstWeekContainsDate

import { getWeek } from 'date-fns'

const date = new Date(2024, 0, 10)

getWeek(date, {
  weekStartsOn: 1,
  firstWeekContainsDate: 4
})

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


Отличие getWeek от getISOWeek

getWeek и getISOWeek часто используются для похожих задач, но их поведение различается.

getISOWeek

  • строго следует ISO-8601
  • неделя всегда начинается с понедельника
  • первая неделя года — та, в которой есть минимум 4 дня нового года
import { getISOWeek } from 'date-fns'

getWeek

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

Пример различий

import { getWeek, getISOWeek } from 'date-fns'

const date = new Date(2024, 0, 1)

getWeek(date, { weekStartsOn: 0 })
getISOWeek(date)

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


Логика вычисления недели

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

  1. Определение дня недели для указанной даты
  2. Смещение даты относительно начала года
  3. Учет weekStartsOn
  4. Проверку, попадает ли дата в первую календарную неделю
  5. Вычисление номера недели на основе количества прошедших недель

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

Календарные интерфейсы

const weekNumber = getWeek(selectedDate, {
  weekStartsOn: 1
})

Используется для отображения номера недели рядом с датой в UI.


Группировка данных по неделям

import { getWeek } from 'date-fns'

const grouped = {}

events.forEach(event => {
  const week = getWeek(event.date, { weekStartsOn: 1 })

  if (!grouped[week]) {
    grouped[week] = []
  }

  grouped[week].push(event)
})

Результат — структура данных, сгруппированная по неделям года.


Аналитика и отчётность

При построении отчётов часто требуется агрегация:

  • продажи по неделям
  • активность пользователей
  • статистика посещений
const weekIndex = getWeek(transaction.date, {
  weekStartsOn: 1,
  firstWeekContainsDate: 4
})

Влияние локали

Хотя getWeek не принимает локаль напрямую, поведение часто синхронизируют с локалями через date-fns/locale.

Пример интеграции через вспомогательные функции:

  • локаль определяет weekStartsOn
  • локаль определяет правило первой недели

Это позволяет строить календарные системы для разных стран.


Пограничные случаи

Переход между годами

Дата в конце декабря может попасть в первую неделю следующего года:

getWeek(new Date(2023, 11, 31))

или наоборот — январские дни могут принадлежать последней неделе предыдущего года.


Разные правила календаря

Одна и та же дата может иметь разные номера недель:

  • в американской системе
  • в европейской системе
  • в ISO-системе

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

Игнорирование weekStartsOn

getWeek(date)

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


Несогласованность в системе

Если:

  • UI использует один weekStartsOn
  • backend использует другой

возникают расхождения в аналитике.


Путаница с ISO-неделями

Использование getWeek вместо getISOWeek в системах, где требуется строгий стандарт ISO, приводит к некорректным отчётам.


Производственные особенности

Функция:

  • не мутирует исходную дату
  • работает детерминированно
  • имеет линейную сложность O(1)
  • подходит для массовой обработки данных

Совместное использование с другими функциями date-fns

getWeek часто применяется вместе с:

  • startOfWeek — начало недели
  • endOfWeek — конец недели
  • format — форматирование дат
  • addWeeks — переход между неделями
import { startOfWeek, endOfWeek, getWeek } from 'date-fns'

const start = startOfWeek(date, { weekStartsOn: 1 })
const end = endOfWeek(date, { weekStartsOn: 1 })
const weekNumber = getWeek(date, { weekStartsOn: 1 })

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

getWeek фактически реализует абстракцию:

  • линейное разбиение года на интервалы фиксированной длины (7 дней)
  • с возможностью сдвига начала координат (weekStartsOn)
  • с адаптацией границ года (firstWeekContainsDate)

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