Работа с днями и неделями

Day.js предоставляет компактный и предсказуемый API для операций с календарными датами, включая манипуляции днями и неделями. Основной принцип заключается в неизменяемости объектов: каждая операция возвращает новый экземпляр даты, не изменяя исходный.


Базовые операции с днями

Работа с днями строится вокруг методов add, subtract, startOf, endOf и доступа к компонентам даты через day().

Добавление и вычитание дней

Операции смещения даты выполняются через единый интерфейс:

import dayjs from "dayjs";

const now = dayjs();

const tomorrow = now.add(1, "day");
const yesterday = now.subtract(1, "day");

Ключевой момент: второй аргумент задаёт единицу измерения. Помимо "day" поддерживаются "week", "month", "year" и другие.

При добавлении дней учитываются календарные переходы:

dayjs("2024-01-31").add(1, "day"); // 2024-02-01

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

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

const date = dayjs("2024-06-15 14:35:20");

const start = date.startOf("day");
const end = date.endOf("day");

Результаты:

  • startOf("day") → 00:00:00.000
  • endOf("day") → 23:59:59.999

Такая нормализация используется при фильтрации записей по диапазону дат.


Извлечение дня недели

День недели доступен через метод day():

const date = dayjs("2024-06-15");

date.day(); // число от 0 до 6

Значения по умолчанию:

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

Изменение дня недели:

dayjs("2024-06-15").day(1); // установить понедельник текущей недели

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


Работа с неделями

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

Стандартная неделя

Метод startOf("week") и endOf("week") зависят от локали. В большинстве конфигураций неделя начинается в воскресенье.

const date = dayjs("2024-06-15");

const weekStart = date.startOf("week");
const weekEnd = date.endOf("week");

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


ISO-недели

ISO-8601 определяет неделю как начинающуюся с понедельника. Для работы с таким форматом используется плагин isoWeek.

Подключение ISO-недель

import dayjs from "dayjs";
import isoWeek from "dayjs/plugin/isoWeek";

dayjs.extend(isoWeek);

После подключения доступны методы:

  • isoWeek()
  • isoWeekday()
  • startOf("isoWeek")
  • endOf("isoWeek")

Номер ISO-недели

dayjs("2024-01-10").isoWeek(); // номер недели в году

ISO-неделя учитывает правило:

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

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


День недели в ISO-формате

dayjs("2024-06-15").isoWeekday();

Значения:

  • 1 — понедельник
  • 7 — воскресенье

Изменение дня недели:

dayjs("2024-06-15").isoWeekday(1);

Работа с номером недели (week plugin)

Для стандартного номера недели используется плагин weekOfYear.

import weekOfYear from "dayjs/plugin/weekOfYear";
dayjs.extend(weekOfYear);

После этого доступен метод:

dayjs("2024-06-15").week();

Различие между week() и isoWeek() заключается в правилах календаря и локали.


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

Стандартная неделя

dayjs("2024-06-15").startOf("week");
dayjs("2024-06-15").endOf("week");

ISO-неделя

dayjs("2024-06-15").startOf("isoWeek");
dayjs("2024-06-15").endOf("isoWeek");

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


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

Недели поддерживают арифметику аналогично дням:

const date = dayjs("2024-06-15");

const nextWeek = date.add(1, "week");
const prevWeek = date.subtract(1, "week");

Смещение эквивалентно добавлению 7 дней, но сохраняет семантическую читаемость кода.


Нормализация недельных диапазонов

Частый сценарий — получение диапазона недели для выборки данных.

const date = dayjs("2024-06-15");

const range = {
  start: date.startOf("isoWeek"),
  end: date.endOf("isoWeek")
};

Такой подход используется при:

  • построении календарей
  • агрегации статистики
  • фильтрации транзакций по неделям

Особенности локализации недель

Локаль влияет на:

  • первый день недели
  • формат отображения
  • поведение startOf("week")

Например, в некоторых локалях неделя начинается с понедельника, что сближает стандартную неделю с ISO-неделей, но не делает их идентичными.


Различие между day, week и weekday

Система API включает несколько уровней работы с днями:

  • day() — абсолютный день недели (0–6)
  • weekday() — локализованный индекс дня недели (плагин weekday)
  • isoWeekday() — ISO-индекс (1–7)

Плагин weekday:

import weekday from "dayjs/plugin/weekday";
dayjs.extend(weekday);

Использование:

dayjs().weekday(0); // первый день недели согласно локали

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

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

const start = dayjs().startOf("month").startOf("week");

const days = Array.from({ length: 42 }, (_, i) =>
  start.add(i, "day")
);

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

const weekKey = dayjs(date).startOf("isoWeek").format("YYYY-MM-DD");

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

const date = dayjs("2024-06-15");
const target = dayjs("2024-06-12");

const inSameWeek =
  date.startOf("isoWeek").isSame(target.startOf("isoWeek"));

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

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

  • переход года (декабрь → январь)
  • високосные годы
  • различие локальных и ISO-недель
  • изменение локали в runtime

Пример перехода года:

dayjs("2020-12-31").isoWeek(); // может относиться к первой неделе следующего года

Комбинирование дней и недель в цепочках

API позволяет строить последовательные трансформации:

dayjs()
  .startOf("isoWeek")
  .add(2, "day")
  .endOf("day");

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


Сравнение дат по дням и неделям

Сравнение по дням

a.isSame(b, "day");

Сравнение по неделям

a.isSame(b, "week");
a.isSame(b, "isoWeek");

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


Инкрементальная логика недель

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

let current = dayjs();

current = current.subtract(1, "week");
current = current.add(2, "week");

Каждая операция сохраняет календарную целостность и учитывает длину месяцев и переходы между ними.


Итоговая структура работы с днями и неделями

  • дни управляются через add, subtract, day, startOf, endOf
  • недели зависят от локали или ISO-стандарта
  • ISO-недели требуют отдельного плагина
  • недельные операции всегда возвращают новые экземпляры даты
  • корректная работа требует явного выбора модели недели: локальная или ISO