В Moment.js работа с датами строится вокруг объектной модели, где
каждая операция изменяет или возвращает новый экземпляр момента времени.
При необходимости скорректировать сразу несколько временных компонентов
используется объектная форма методов set, add
и subtract. Такой подход позволяет описывать сложные
трансформации даты в одном выражении, избегая цепочек однотипных
вызовов.
Ключевая особенность Moment.js — мутабельность
объектов. Любое изменение затрагивает исходный экземпляр, если
не создаётся его копия через clone().
setМетод set принимает объект, содержащий произвольный
набор временных компонентов. Это основной инструмент для атомарного
задания даты.
const m = moment();
m.set({
year: 2025,
month: 0,
date: 15,
hour: 10,
minute: 30,
second: 0
});
Возможные ключи соответствуют стандартной модели времени Moment.js:
year или yearsmonth или months (0–11)date или dayhourminutesecondmillisecondПорядок внутри объекта не имеет значения: библиотека нормализует значения после применения всех изменений.
При установке нескольких полей одновременно Moment.js выполняет автоматическую корректировку диапазонов. Например, выход за пределы допустимых значений приводит к «переносу» в старшие единицы времени.
const m = moment();
m.set({
month: 0,
date: 40
});
Дата автоматически преобразуется в корректное значение февраля с соответствующим смещением.
Это поведение важно учитывать при пакетной установке значений, поскольку итоговый результат зависит не только от входных данных, но и от внутренних правил нормализации.
addМетод add позволяет увеличивать дату сразу по нескольким
компонентам, используя объектную форму аргумента.
const m = moment();
m.add({
days: 10,
months: 2,
years: 1,
hours: 5
});
Каждое поле применяется последовательно, но внутри одной операции. Это означает, что итоговое значение формируется с учётом промежуточных состояний, хотя внешне операция выглядит атомарной.
Поддерживаемые ключи аналогичны set, но интерпретируются
как приращения:
yearsmonthsweeksdayshoursminutessecondsmillisecondsaddХотя объект передаётся целиком, Moment.js применяет изменения в фиксированном порядке внутренних единиц времени: от больших к меньшим. Это предотвращает некорректные переносы при сложных комбинациях.
Пример:
const m = moment('2025-01-31');
m.add({
months: 1,
days: 1
});
Результат зависит от того, как интерпретируется конец месяца и переход в следующий календарный период. В таких случаях важно учитывать календарную неоднородность месяцев.
subtractМетод subtract является симметричным к add,
но выполняет обратное смещение.
const m = moment();
m.subtract({
days: 7,
months: 1,
hours: 3
});
Логика применения идентична add, включая порядок
обработки полей и нормализацию результата.
set, add и subtractПри одновременном использовании нескольких методов критично понимать порядок выполнения. Moment.js применяет изменения последовательно в порядке вызова.
const m = moment();
m.set({ year: 2025, month: 5 })
.add({ days: 10 })
.subtract({ hours: 2 });
Каждый шаг изменяет состояние объекта, и следующий шаг опирается уже на обновлённую дату.
Типичная ошибка — ожидание независимого применения операций. На практике результат всегда кумулятивный.
Поскольку объект Moment.js изменяемый, повторное использование одной
и той же переменной приводит к накоплению изменений. Для предотвращения
побочных эффектов используется clone().
const base = moment({ year: 2025, month: 0, date: 1 });
const modified = base.clone().add({
days: 10,
months: 1
});
Исходный объект остаётся неизменным, а все преобразования выполняются на копии.
Одновременное изменение нескольких полей часто используется при:
Пример формирования временного окна:
const start = moment().set({
hour: 9,
minute: 0,
second: 0
});
const end = start.clone().add({
hours: 8,
minutes: 30
});
Такой подход позволяет описывать интервалы без последовательных вызовов для каждого поля.
При одновременной работе с месяцами, днями и годами возникают неоднозначности из-за различий в длине месяцев и переходах через високосные годы.
const m = moment('2024-01-31');
m.add({
months: 1,
days: 1
});
Результат зависит от внутренней логики календаря Moment.js: сначала происходит смещение месяца, затем добавление дней, что может привести к неожиданным итоговым датам.
Moment.js допускает несколько вариантов ключей в объектах:
m.add({
day: 2,
days: 2,
d: 2
});
Однако на практике используется стандартный набор полных названий, поскольку сокращения и синонимы могут снижать читаемость и усложнять поддержку кода.
При пакетных операциях изменения выполняются в рамках текущей временной зоны объекта. Это означает, что переходы через границы летнего и зимнего времени могут приводить к дополнительным смещениям часов.
const m = moment.tz('2025-03-29 12:00', 'Europe/Berlin');
m.add({
days: 1,
hours: 12
});
При таких сценариях важно учитывать возможные скачки времени, связанные с политикой временной зоны.
Объектная форма предпочтительна при изменении нескольких параметров одновременно:
m.add({ years: 1, months: 2, days: 3 });
Цепочная форма:
m.add(1, 'years')
.add(2, 'months')
.add(3, 'days');
Обе формы эквивалентны, но различаются по:
Повторное использование изменённого объекта
const a = moment();
const b = a.add({ days: 1 });
const c = a.add({ days: 2 });
Оба b и c ссылаются на один и тот же
изменённый объект.
Ожидание неизменяемости
Moment.js не создаёт новые экземпляры автоматически. Любое изменение затрагивает исходное значение.
Неверная интерпретация месяцев
Месяцы в Moment.js индексируются с нуля:
При пакетной установке это часто приводит к смещению календарных значений.
Одновременное изменение нескольких полей в Moment.js основано на трёх механизмах:
set, add,
subtractЭта комбинация позволяет выполнять сложные преобразования даты в одном вызове, сохраняя при этом детерминированную модель вычислений внутри библиотеки.