Работа с датами в Day.js строится вокруг иммутабельной модели: каждое преобразование возвращает новый объект даты, не изменяя исходный. Это особенно важно при сложных вычислениях, где последовательные операции добавления и вычитания должны оставаться предсказуемыми. Одним из расширенных способов управления временем является использование объектов при добавлении и вычитании, что становится доступным через плагин objectSupport.
Стандартный API Day.js использует сигнатуру:
dayjs().add(1, 'day')
dayjs().subtract(2, 'month')
Однако при работе с комплексными интервалами такой подход становится громоздким. Например, необходимо прибавить одновременно дни, часы и минуты. В таких случаях используется объектная форма:
dayjs().add({
days: 2,
hours: 3,
minutes: 15
})
Объектный подход делает выражение более читаемым и структурированным, особенно при работе с конфигурациями временных интервалов, поступающими из API или пользовательского ввода.
По умолчанию Day.js не интерпретирует объекты в методах add и subtract. Для активации этой функциональности используется плагин objectSupport:
import dayjs from 'dayjs'
import objectSupport from 'dayjs/plugin/objectSupport'
dayjs.extend(objectSupport)
После подключения становится доступна передача объектов в методы изменения даты.
Важно учитывать, что без подключения плагина попытка передать объект приведёт к некорректной интерпретации или игнорированию параметров.
Объект, передаваемый в add или subtract, может содержать комбинацию следующих ключей:
Пример комбинированного интервала:
dayjs().add({
years: 1,
months: 6,
days: 10,
hours: 4
})
Каждое поле интерпретируется независимо, после чего суммарное смещение применяется к исходной дате.
При использовании объектной формы важно понимать, что Day.js применяет значения последовательно по внутренней логике преобразования календаря. Например:
dayjs('2024-01-31')
.add({ months: 1 })
Результат зависит от правил календарной нормализации. В случае с январём добавление одного месяца может привести к февралю с корректировкой дня, если целевая дата не существует.
Аналогично:
dayjs('2024-01-31')
.add({ days: 10 })
здесь добавление дней происходит без календарных неоднозначностей, так как дни интерпретируются линейно.
Метод subtract также поддерживает объектную форму при активированном objectSupport:
dayjs().subtract({
days: 5,
hours: 2
})
Семантически это эквивалентно добавлению отрицательных значений, однако объектная форма делает код более выразительным при работе с симметричными временными изменениями.
Пример с комбинированным вычитанием:
dayjs('2025-06-15')
.subtract({
months: 2,
weeks: 1,
minutes: 30
})
При передаче объекта Day.js преобразует ключи в последовательные вызовы внутренних операций добавления/вычитания. Концептуально это эквивалентно цепочке:
dayjs()
.add(2, 'days')
.add(3, 'hours')
.add(15, 'minutes')
Но фактически выполняется единый проход с нормализацией результата.
Это важно при понимании того, как взаимодействуют различные единицы измерения. Например, добавление 90 минут не сохраняется как «90 минут», а преобразуется в 1 час 30 минут в итоговой дате.
Объектная форма требует корректного использования ключей. Неверные названия игнорируются:
dayjs().add({
dayz: 5, // будет проигнорировано
days: 5 // будет применено
})
Также важно различать:
day и days (в контексте Day.js
используется множественная форма)week и weeksmonth и monthsЕдинообразие ключей критично при динамической генерации объектов интервала.
Часто объект интервала формируется из внешних данных:
const interval = {
days: Number(inputDays),
hours: Number(inputHours)
}
dayjs().add(interval)
Такой подход упрощает интеграцию с формами и API, где данные приходят в структурированном виде.
При этом Day.js не выполняет строгую валидацию типов, поэтому передача строковых значений может привести к неожиданным результатам:
dayjs().add({
days: '5' // будет приведено к числу, но поведение зависит от контекста
})
Поэтому на уровне приложения обычно выполняется явное преобразование типов.
Объектная форма не ограничивает последовательность операций. Можно комбинировать добавление и вычитание:
dayjs()
.add({ days: 10 })
.subtract({ hours: 3 })
Каждая операция создаёт новый экземпляр даты, что позволяет строить цепочки преобразований без побочных эффектов.
При работе с месяцами и годами возникает особенность нормализации дат:
dayjs('2024-03-31')
.add({ months: 1 })
Если следующий месяц не содержит 31 числа, Day.js автоматически корректирует дату до последнего допустимого дня месяца.
Аналогично:
dayjs('2023-02-28')
.add({ years: 1 })
переносит дату в следующий год с учётом календарных ограничений.
Объектная форма удобна, но внутри может приводить к нескольким последовательным вычислениям. В большинстве сценариев разница незначительна, однако при массовых операциях над большими наборами дат предпочтительнее использовать явные вызовы add/subtract с фиксированными единицами.
// более предсказуемый вариант для циклов
for (let i = 0; i < 1000; i++) {
date = date.add(1, 'day')
}
Объектная форма больше ориентирована на читаемость, чем на микрооптимизацию.
Объекты интервалов часто используются как часть бизнес-логики:
const expirationPolicy = {
days: 30,
hours: 12
}
const expiresAt = dayjs(createdAt).add(expirationPolicy)
Такой подход позволяет централизовать временные правила и применять их в разных частях приложения без дублирования логики.
После применения объектных операций Day.js всегда возвращает нормализованную дату в пределах стандартного диапазона времени. Это означает:
Таким образом итоговый объект всегда представляет валидную дату независимо от сложности входного интервала.