Цепочки вызовов

Цепочки вызовов в Day.js основаны на принципе последовательного применения методов, при котором каждый вызов возвращает новый экземпляр даты, позволяя строить выразительные и компактные выражения для преобразований времени. Такой подход формирует читаемую и предсказуемую модель работы с датами, исключая необходимость промежуточных переменных и снижая риск побочных эффектов.

Основой цепочечного API в Day.js является неизменяемость (immutability). Каждый метод, изменяющий дату, не модифицирует исходный объект, а возвращает новый экземпляр с применёнными изменениями.

Ключевая особенность:

Каждый вызов метода возвращает новый объект Day.js

import dayjs from 'dayjs';

const d1 = dayjs('2026-01-01');
const d2 = d1.add(5, 'day');

console.log(d1.format()); // исходная дата не изменилась
console.log(d2.format()); // новая дата

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

Базовая структура цепочки

Цепочка строится последовательным вызовом методов, где результат каждого шага передаётся дальше:

dayjs('2026-01-01')
  .add(10, 'day')
  .subtract(2, 'month')
  .year(2027)
  .format('YYYY-MM-DD');

Каждый этап выполняет строго одно преобразование:

  • add — добавление времени
  • subtract — вычитание времени
  • year — установка конкретного года
  • format — финальное преобразование в строку

Подобная структура повышает читаемость даже при сложных преобразованиях дат.

Математика времени в цепочках

Методы изменения даты позволяют выстраивать последовательности временных вычислений без промежуточных переменных:

const result = dayjs()
  .add(1, 'year')
  .add(2, 'month')
  .subtract(10, 'day');

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

Манипуляции с календарными единицами

Day.js поддерживает работу с различными единицами времени, что делает цепочки универсальными:

dayjs('2026-05-23')
  .startOf('month')
  .add(1, 'week')
  .endOf('day')
  .format('YYYY-MM-DD HH:mm:ss');

Используемые методы:

  • startOf(unit) — переход к началу периода
  • endOf(unit) — переход к концу периода
  • add(value, unit) — добавление интервала
  • subtract(value, unit) — вычитание интервала

Комбинация этих операций позволяет формировать сложные календарные правила.

Цепочки и форматирование результата

Форматирование обычно завершает цепочку, так как преобразует объект Day.js в строку:

const formatted = dayjs()
  .add(3, 'day')
  .hour(14)
  .minute(30)
  .second(0)
  .format('DD.MM.YYYY HH:mm');

Метод format не возвращает объект Day.js, поэтому дальнейшее продолжение цепочки невозможно после его вызова.

Установка и получение значений внутри цепочек

Day.js предоставляет методы-геттеры и сеттеры, которые также поддерживают цепочечный стиль:

dayjs('2026-05-23')
  .year(2028)
  .month(11)
  .date(15)
  .format('YYYY-MM-DD');

Особенности поведения:

  • при передаче аргумента метод работает как setter
  • без аргумента — как getter (но прерывает цепочку при использовании результата)

Getter-формы обычно не применяются внутри цепочек, так как возвращают примитивные значения.

Смешивание операций разных типов

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

dayjs()
  .set('day', 1)
  .add(2, 'week')
  .subtract(3, 'day')
  .set('hour', 12)
  .format('YYYY-MM-DD HH:mm');

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

Работа с плагинами в цепочках

Расширения Day.js добавляют дополнительные методы, которые органично встраиваются в цепочную модель.

Пример с UTC:

import utc from 'dayjs/plugin/utc';
dayjs.extend(utc);

dayjs()
  .utc()
  .add(1, 'day')
  .format();

Плагины не нарушают принцип цепочек: каждый дополнительный метод возвращает новый экземпляр Day.js.

Внутренняя логика неизменяемости

Каждый вызов метода создаёт новый объект, копируя внутреннее состояние:

  • timestamp
  • локальные настройки
  • метаданные (например, UTC-флаг)

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

const base = dayjs('2026-01-01');

const a = base.add(1, 'day');
const b = base.add(2, 'day');

a и b полностью независимы.

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

Некорректное использование чаще всего связано с попыткой повторно использовать результат форматирования:

const wrong = dayjs()
  .add(1, 'day')
  .format()
  .add(2, 'day'); // ошибка: строка не поддерживает методы Day.js

После format() объект перестаёт быть экземпляром Day.js, поэтому дальнейшие вызовы невозможны.

Другой частый случай — ожидание изменения исходного объекта:

const base = dayjs();
base.add(1, 'day');

console.log(base.format()); // исходное значение

Изменение не происходит, так как результат add не сохранён.

Композиция сложных выражений

Цепочки позволяют формировать выражения, эквивалентные многошаговым вычислениям:

dayjs('2026-01-01')
  .add(1, 'year')
  .startOf('year')
  .add(6, 'month')
  .endOf('month')
  .format('YYYY-MM-DD');

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