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

Понятие «начала недели» в календарной модели Day.js

В Day.js неделя не является фиксированным интервалом, жёстко привязанным к конкретному дню календаря. Определение первого дня недели зависит от текущей локали и её параметра weekStart. Это означает, что одинаковые операции над датами могут давать разные результаты в зависимости от языковой или региональной настройки окружения.

Ключевой момент: startOf('week') вычисляется относительно локали, а не универсального стандарта

dayjs().startOf('week')

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


Локали и параметр weekStart

Каждая локаль в Day.js может содержать поле weekStart, определяющее индекс первого дня недели:

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

Например:

import dayjs from 'dayjs'
import 'dayjs/locale/ru'

dayjs.locale('ru')

В локали ru начало недели соответствует понедельнику (weekStart: 1), поэтому:

dayjs().startOf('week')

вернёт понедельник текущей недели.

В английской локали en (по умолчанию):

dayjs.locale('en')

weekStart равен 0, и неделя начинается с воскресенья.


Влияние startOf(‘week’) на вычисления

Метод startOf('week') приводит дату к началу недели, учитывая локаль:

dayjs('2026-05-22').startOf('week')

Результат будет различаться:

  • при weekStart = 0 → воскресенье 17 мая 2026
  • при weekStart = 1 → понедельник 18 мая 2026

Это поведение критично для:

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

Явная настройка локали с weekStart

В Day.js локаль можно переопределить, задав собственный weekStart.

import dayjs from 'dayjs'

dayjs.locale({
  name: 'custom-ru',
  weekStart: 1,
  weekdays: [
    'понедельник',
    'вторник',
    'среда',
    'четверг',
    'пятница',
    'суббота',
    'воскресенье'
  ],
  months: []
}, null, true)

После активации:

dayjs.locale('custom-ru')

Все операции с неделями начинают использовать новую конфигурацию.


Глобальное и локальное влияние настроек

Day.js использует глобальное состояние локали, поэтому:

dayjs.locale('ru')

меняет поведение всех последующих вызовов startOf('week').

Однако можно временно переключать локаль:

dayjs().locale('en').startOf('week')
dayjs().locale('ru').startOf('week')

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


Начало недели и методы endOf

Логика симметрична и для конца недели:

dayjs().endOf('week')

Этот метод возвращает последний момент недели (23:59:59.999), и также зависит от weekStart.

Если неделя начинается в понедельник, то конец недели приходится на воскресенье.


Взаимосвязь с weekOfYear

Для корректной работы недельных расчётов часто используется плагин weekOfYear:

import weekOfYear from 'dayjs/plugin/weekOfYear'
dayjs.extend(weekOfYear)

Он также опирается на локаль:

dayjs('2026-01-01').week()

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


Практическое влияние на бизнес-логику

При построении систем аналитики и отчётности важно учитывать:

  • различие ISO-недель и локальных недель Day.js
  • несоответствие между серверной и клиентской локалью
  • различие региональных стандартов (США vs Европа)

Типичный пример ошибки:

const start = dayjs(date).startOf('week')
const end = dayjs(date).endOf('week')

Если сервер использует en, а клиент ru, диапазоны недель будут различаться, что приводит к несогласованным отчётам.


Стабилизация начала недели через фиксированную локаль

Для устранения неоднозначности часто фиксируют локаль независимо от пользовательских настроек:

dayjs.locale('en') // фиксированное воскресенье как начало недели

или

dayjs.locale('ru') // фиксированный понедельник

Такой подход делает вычисления детерминированными.


Альтернативный способ: ручное смещение недели

При необходимости игнорировать локали можно явно вычислять начало недели:

const startOfWeek = (date, start = 1) => {
  const d = dayjs(date)
  const day = d.day()
  const diff = (day < start ? 7 : 0) + day - start
  return d.subtract(diff, 'day').startOf('day')
}

Такой метод полностью отключает зависимость от локали Day.js и задаёт бизнес-логику явно.


Работа с числовыми значениями дня недели

Метод day() возвращает индекс дня недели:

dayjs().day()
  • 0 — воскресенье
  • 1 — понедельник
  • 6 — суббота

Он не зависит от weekStart, что важно при сравнении с startOf('week'), так как:

  • day() — фиксированная шкала
  • startOf('week') — локализованная логика

Сценарии, где локаль критична

Особенно сильное влияние настройки начала недели проявляется в задачах:

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

Во всех этих случаях ошибка в weekStart приводит к смещению границ данных на 1–2 дня, что искажает агрегированные результаты.