Операции с неделями

В Luxon работа с неделями строится вокруг ISO-8601 стандарта, где неделя:

  • начинается в понедельник
  • имеет номер от 1 до 52/53
  • принадлежит не календарному году, а недельному году (weekYear)

Ключевые свойства объекта DateTime:

  • weekNumber — номер недели в году
  • weekYear — год, к которому принадлежит неделя
  • weekday — день недели (1 = понедельник, 7 = воскресенье)
import { DateTime } from "luxon";

const dt = DateTime.local(2026, 1, 24);

dt.weekNumber; // например: 4
dt.weekYear;   // например: 2026
dt.weekday;    // 6 (суббота)

Важно учитывать: weekYear может отличаться от календарного года, если дата находится на границе декабря и января.


Получение начала и конца недели

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

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

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

Результат — дата, приведённая к понедельнику 00:00:00 текущей недели.

Конец недели

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

Результат — воскресенье 23:59:59.999 текущей недели.

Эти методы учитывают локаль, но при стандартной конфигурации Luxon опирается на ISO-неделю.


Смещение по неделям

Luxon предоставляет арифметику через plus и minus, где недели задаются как единица измерения.

const nextWeek = dt.plus({ weeks: 1 });
const previousWeek = dt.minus({ weeks: 2 });

При таком смещении:

  • сохраняется день недели и время
  • изменяется только календарная позиция на оси времени

Особенность: переход через границы года автоматически корректирует weekYear.


Разница между датами в неделях

Для вычисления разницы используется метод diff.

const a = DateTime.local(2026, 1, 1);
const b = DateTime.local(2026, 2, 1);

const diff = b.diff(a, "weeks").weeks;

Результат — дробное число недель, отражающее точную разницу во времени.

При необходимости округления:

Math.floor(diff);

или

Math.round(diff);

Создание даты по номеру недели

Luxon позволяет строить дату напрямую из параметров недельной системы.

const dt = DateTime.fromObject({
  weekYear: 2026,
  weekNumber: 10,
  weekday: 1
});

Такой способ полезен при работе с:

  • производственными календарями
  • планированием по неделям
  • отчётными системами

Если weekday не указан, по умолчанию используется понедельник.


Изменение недели у существующей даты

Изменение компонентов недели выполняется через set.

const upd ated = dt.se t({
  weekNumber: 12,
  weekYear: 2026
});

При этом важно:

  • weekNumber и weekYear должны быть согласованы
  • несоответствие может привести к сдвигу даты в соседний год

Также можно менять день недели:

const moved = dt.set({ weekday: 5 });

Итерации по неделям

Частая задача — проход по диапазону недель.

let current = DateTime.local(2026, 1, 1).startOf("week");
const end = DateTime.local(2026, 3, 1);

while (current < end) {
  // работа с неделей
  console.log(current.weekNumber, current.weekYear);

  current = current.plus({ weeks: 1 });
}

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


Форматирование недель

Luxon поддерживает ISO-представления, полезные для отчётности и логирования.

Базовый формат недели

dt.toFormat("kkkk-'W'WW");

Где:

  • kkkk — weekYear
  • WW — номер недели с ведущим нулём

Пример: 2026-W04

ISO-неделя

dt.toISOWeekDate();

Формат: YYYY-Www-D Пример: 2026-W04-6


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

Работа с неделями требует учёта переходных зон:

Неделя может принадлежать соседнему году

const dt = DateTime.local(2026, 1, 1);

dt.weekYear;   // может быть 2025
dt.weekNumber; // 52 или 53

Это связано с тем, что первая неделя года — это неделя, содержащая первый четверг января.


Локализация начала недели

Хотя ISO-норма фиксирует понедельник как начало недели, Luxon позволяет учитывать локаль:

const dt = DateTime.local().setLocale("en");

Однако большинство недельных операций (weekNumber, weekYear) остаются ISO-ориентированными, а локаль влияет в основном на форматирование и startOf('week').


Комбинированные операции с неделями

Практическая работа часто включает цепочки преобразований:

const rangeStart = DateTime.local(2026, 1, 1)
  .startOf("week");

const rangeEnd = rangeStart
  .plus({ weeks: 8 })
  .endOf("week");

Или получение начала следующей недели с нормализацией времени:

const nextWeekStart = dt
  .startOf("week")
  .plus({ weeks: 1 });

Сравнение недельных интервалов

Для проверки принадлежности к одной неделе достаточно сравнить weekNumber и weekYear:

function isSameWeek(a, b) {
  return a.weekNumber === b.weekNumber && a.weekYear === b.weekYear;
}

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

a.startOf("week").equals(b.startOf("week"));

Практика календарного моделирования

Недельная модель Luxon особенно полезна при:

  • построении календарей задач
  • расчёте спринтов в разработке
  • финансовой отчётности по ISO-неделям

Типичный шаблон агрегации:

const grouped = {};

dates.forEach(d => {
  const key = `${d.weekYear}-W${d.weekNumber}`;
  grouped[key] = (grouped[key] || 0) + 1;
});

Так формируется структура данных, независимая от месячной логики.