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

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

Основной инструмент для работы с недельными границами — DateTime и методы startOf('week') и endOf('week').

В Luxon неделя не является универсальной единицей с фиксированным началом в понедельник. Поведение зависит от локали, установленной у экземпляра DateTime.

  • В локалях типа en-US неделя начинается в воскресенье
  • В локалях типа en-GB, ru, de неделя начинается в понедельник
  • ISO-логика (международный стандарт) использует понедельник как первый день недели

Локаль задаётся через:

import { DateTime } from "luxon";

const dt = DateTime.now().setLocale("en-GB");

или глобально через настройки (если используется конфигурация приложения).

Локаль влияет на то, как интерпретируются:

  • начало недели
  • конец недели
  • расчёт startOf('week')
  • расчёт endOf('week')

Начало недели: startOf(‘week’)

Метод startOf('week') возвращает дату и время, соответствующие началу недели в текущей локали.

const dt = DateTime.fromISO("2026-05-23T15:30:00").setLocale("en-GB");

const start = dt.startOf("week");

Если локаль европейская (например, en-GB), результат будет понедельник 00:00:00.000.

Пример:

DateTime.fromISO("2026-05-23").setLocale("en-GB").startOf("week").toISO();

Результат:

2026-05-18T00:00:00.000+03:00 (в зависимости от зоны)

Если локаль американская:

const dt = DateTime.fromISO("2026-05-23").setLocale("en-US");
dt.startOf("week");

Неделя начинается в воскресенье, и результат будет смещён на один день назад относительно европейской модели.

Важная особенность

startOf('week') всегда:

  • обнуляет часы, минуты, секунды и миллисекунды
  • возвращает начало суток
  • учитывает локаль текущего объекта DateTime

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

Конец недели: endOf(‘week’)

Метод endOf('week') возвращает последний момент недели в рамках локали.

const dt = DateTime.fromISO("2026-05-23").setLocale("en-GB");

const end = dt.endOf("week");

Результат соответствует воскресенью 23:59:59.999 (для европейских локалей).

Пример:

DateTime.fromISO("2026-05-23")
  .setLocale("en-GB")
  .endOf("week")
  .toISO();

Типичный результат:

2026-05-24T23:59:59.999+03:00

Семантика endOf(‘week’)

Метод выполняет два шага:

  1. Переводит дату в последний день недели согласно локали
  2. Устанавливает время на максимально возможное значение дня

Это делает его пригодным для:

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

Диапазон недели как интервал

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

const dt = DateTime.fromISO("2026-05-23").setLocale("en-GB");

const start = dt.startOf("week");
const end = dt.endOf("week");

Получается замкнутый интервал:

  • start: понедельник 00:00
  • end: воскресенье 23:59:59.999

Такой диапазон используется в SQL-подобных фильтрах:

const events = events.filter(e =>
  DateTime.fromISO(e.date) >= start &&
  DateTime.fromISO(e.date) <= end
);

ISO-неделя и отличие от локальной недели

Luxon поддерживает ISO-нумерацию недели через свойства:

  • weekNumber
  • weekYear

ISO-неделя определяется по правилам:

  • неделя начинается в понедельник
  • первая неделя года — та, в которой есть минимум 4 дня нового года
const dt = DateTime.fromISO("2026-01-01");

dt.weekNumber;
dt.weekYear;

Важно различать:

  • startOf('week') — локальная логика
  • ISO-неделя — стандарт календарной нумерации

Прямого метода startOf('isoWeek') нет, поэтому границы ISO-недели вычисляются через weekYear и weekNumber:

const isoStart = DateTime.fromObject({
  weekYear: dt.weekYear,
  weekNumber: dt.weekNumber
}).startOf("week");

Такой подход нормализует дату к началу ISO-недели.

Влияние временной зоны

Неделя в Luxon всегда привязана к конкретной временной зоне объекта DateTime.

const dt = DateTime.fromISO("2026-05-23T12:00:00", {
  zone: "Europe/Moscow"
});

При изменении зоны:

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

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

Типичные ошибки при работе с неделей

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

DateTime.now().startOf("week")

Без явного setLocale результат может отличаться от ожидаемого, особенно в системах, где дефолтная локаль — американская.

Смешивание ISO-недели и локальной недели

Использование weekNumber для одной логики и startOf('week') для другой приводит к несоответствиям диапазонов.

Неправильное сравнение дат

Luxon-объекты нельзя корректно сравнивать без нормализации:

dt1 >= dt2 // некорректный подход

Правильный способ:

dt1.toMillis() >= dt2.toMillis()

Построение недельных диапазонов вручную

Иногда требуется явное управление границами недели:

function getWeekRange(date) {
  const dt = DateTime.fromISO(date).setLocale("en-GB");

  return {
    start: dt.startOf("week"),
    end: dt.endOf("week")
  };
}

Для ISO-логики:

function getISOWeekRange(date) {
  const dt = DateTime.fromISO(date);

  const monday = DateTime.fromObject({
    weekYear: dt.weekYear,
    weekNumber: dt.weekNumber
  }).startOf("week");

  return {
    start: monday,
    end: monday.endOf("week")
  };
}

Поведение на границах года

Недели часто пересекают границы года:

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

Luxon сохраняет целостность недельного интервала, не обрезая его по границам года.

DateTime.fromISO("2025-12-31").startOf("week");

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

Практическое значение недельных границ

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

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

Использование startOf('week') и endOf('week') позволяет унифицировать временные диапазоны без ручной арифметики дат и учёта календарных исключений