Начало и конец недели

Работа с границами недели в date-fns строится вокруг двух базовых функций: startOfWeek и endOfWeek. Обе функции возвращают новый объект Date, нормализованный до начала или конца недели с учётом выбранной конфигурации календаря.


Функция startOfWeek(date, options?) возвращает дату, приведённую к началу недели.

import { startOfWeek } from 'date-fns';

const date = new Date(2026, 0, 24); // 24 января 2026
const result = startOfWeek(date);

console.log(result);

По умолчанию началом недели считается воскресенье (индекс дня 0). Это поведение соответствует стандарту en-US календаря.

Изменение дня начала недели

Ключевая настройка — weekStartsOn. Она определяет, какой день считается первым в неделе.

import { startOfWeek } from 'date-fns';

const date = new Date(2026, 0, 24);

// Неделя начинается с понедельника
const result = startOfWeek(date, { weekStartsOn: 1 });

console.log(result);

Значения параметра:

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

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


Конец недели: endOfWeek

Функция endOfWeek(date, options?) возвращает последний момент недели, включая время до 23:59:59.999.

import { endOfWeek } from 'date-fns';

const date = new Date(2026, 0, 24);
const result = endOfWeek(date);

console.log(result);

Как и в случае с началом недели, поведение зависит от weekStartsOn.

import { endOfWeek } from 'date-fns';

const date = new Date(2026, 0, 24);

const result = endOfWeek(date, { weekStartsOn: 1 });

console.log(result);

Конец недели автоматически пересчитывается как:

  • начало недели + 6 дней
  • с установкой времени в 23:59:59.999

Связь между startOfWeek и endOfWeek

Обе функции используют одну и ту же логику определения недели. Разница заключается только в смещении:

  • startOfWeek фиксирует нижнюю границу диапазона
  • endOfWeek фиксирует верхнюю границу диапазона

При одинаковых параметрах weekStartsOn они всегда образуют непрерывный интервал из 7 дней.

import { startOfWeek, endOfWeek } from 'date-fns';

const date = new Date(2026, 0, 24);

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

console.log(start);
console.log(end);

Локали и календарные правила

Помимо weekStartsOn, date-fns поддерживает локализацию через объект locale. Некоторые локали содержат встроенные правила начала недели.

import { startOfWeek } from 'date-fns';
import { ru } from 'date-fns/locale';

const date = new Date(2026, 0, 24);

const result = startOfWeek(date, {
  locale: ru
});

console.log(result);

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

Пример комбинированной настройки:

startOfWeek(date, {
  weekStartsOn: 1,
  locale: ru
});

Приоритет параметров:

  1. weekStartsOn
  2. locale.options.weekStartsOn
  3. значение по умолчанию (0)

Временная составляющая и нормализация даты

startOfWeek и endOfWeek работают не только с днём, но и с временем.

startOfWeek

Устанавливает:

  • 00:00:00.000

endOfWeek

Устанавливает:

  • 23:59:59.999

Это важно при сравнении дат:

import { startOfWeek, endOfWeek } from 'date-fns';

const date = new Date();

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

const isInWeek = date >= start && date <= end;

Примеры практического применения

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

import { startOfWeek } from 'date-fns';

function groupByWeek(dates) {
  const map = new Map();

  dates.forEach((d) => {
    const key = startOfWeek(d, { weekStartsOn: 1 }).toISOString();

    if (!map.has(key)) {
      map.set(key, []);
    }

    map.get(key).push(d);
  });

  return map;
}

Построение диапазона календаря

import { startOfWeek, endOfWeek } from 'date-fns';

function getWeekRange(date) {
  return {
    from: startOfWeek(date, { weekStartsOn: 1 }),
    to: endOfWeek(date, { weekStartsOn: 1 })
  };
}

Проверка попадания даты в неделю

import { startOfWeek, endOfWeek } from 'date-fns';

function isSameWeek(date, target) {
  const start = startOfWeek(target, { weekStartsOn: 1 });
  const end = endOfWeek(target, { weekStartsOn: 1 });

  return date >= start && date <= end;
}

Особенности работы с JavaScript Date

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

Следствия:

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

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

Несовпадение начала недели

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

startOfWeek(date, { weekStartsOn: 0 });
startOfWeek(date, { weekStartsOn: 1 });

Эти выражения дают разные результаты для одной и той же даты.


Игнорирование локали

Передача locale без понимания его настроек может привести к неожиданному началу недели.

startOfWeek(date, { locale: ru });

Если локаль определяет понедельник как начало недели, результат будет отличаться от дефолтного поведения.


Сравнение дат без нормализации

Сравнение Date объектов без приведения к границам недели часто даёт некорректные результаты:

date1.getTime() === date2.getTime()

При недельной логике корректнее использовать startOfWeek для приведения к единому виду перед сравнением.


Комбинирование с другими функциями date-fns

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

  • addWeeks
  • subWeeks
  • eachDayOfInterval
  • format

Пример генерации дней недели:

import { startOfWeek, endOfWeek, eachDayOfInterval } from 'date-fns';

const start = startOfWeek(new Date(), { weekStartsOn: 1 });
const end = endOfWeek(new Date(), { weekStartsOn: 1 });

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

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


Поведение при переходе между месяцами и годами

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

import { startOfWeek, endOfWeek } from 'date-fns';

const date = new Date(2025, 11, 31);

startOfWeek(date, { weekStartsOn: 1 });
endOfWeek(date, { weekStartsOn: 1 });

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