Операция вычитания времени в Moment.js основана на изменении текущего
временного значения с помощью метода subtract, который
позволяет уменьшать дату или время на заданный интервал. Поддерживаются
различные единицы измерения, включая дни, месяцы, годы, часы, минуты,
секунды и миллисекунды. Работа метода опирается на внутреннюю мутацию
объекта Moment, что критично для понимания поведения цепочек
вызовов.
Базовая форма метода:
moment().subtract(Number, String);
moment().subtract(Number, String, Boolean);
Первый аргумент задаёт величину вычитания, второй — единицу измерения.
Примеры использования:
moment().subtract(1, 'days');
moment().subtract(2, 'months');
moment().subtract(10, 'minutes');
moment().subtract(500, 'milliseconds');
Допустимые единицы измерения включают:
В некоторых версиях Moment.js допускаются сокращённые формы:
moment().subtract(1, 'y');
moment().subtract(1, 'M');
moment().subtract(1, 'd');
moment().subtract(1, 'h');
moment().subtract(1, 'm');
moment().subtract(1, 's');
Ключевая особенность subtract заключается в том, что
операция изменяет исходный объект:
const m = moment('2026-01-10');
m.subtract(1, 'days');
console.log(m.format('YYYY-MM-DD')); // 2026-01-09
Повторное использование исходной переменной приводит к накоплению изменений:
const m = moment('2026-01-10');
m.subtract(1, 'days');
m.subtract(2, 'days');
console.log(m.format('YYYY-MM-DD')); // 2026-01-07
Для предотвращения побочных эффектов используется клонирование:
const m1 = moment('2026-01-10');
const m2 = m1.clone().subtract(5, 'days');
console.log(m1.format('YYYY-MM-DD')); // 2026-01-10
console.log(m2.format('YYYY-MM-DD')); // 2026-01-05
Метод поддерживает последовательное применение разных единиц:
moment('2026-01-10')
.subtract(1, 'years')
.subtract(2, 'months')
.subtract(10, 'days');
Эквивалентная форма с объектом:
moment('2026-01-10').subtract({
years: 1,
months: 2,
days: 10
});
Объектная форма удобна для комплексных операций, снижая количество вызовов методов и повышая читаемость.
Некоторые единицы времени зависят от календаря:
Вычитание месяцев учитывает различную длину месяцев:
moment('2026-03-31').subtract(1, 'month');
Результат зависит от правил нормализации дат: если целевой месяц не содержит соответствующего числа дня, происходит корректировка в пределах последнего дня месяца.
moment('2024-02-29').subtract(1, 'year');
Переход из високосного года в обычный приводит к корректировке даты, поскольку 29 февраля отсутствует.
При вычитании часов и минут учитываются переходы через сутки:
moment('2026-01-10T00:30:00').subtract(2, 'hours');
Результат переносится на предыдущий день при выходе за границы суток.
Подобное поведение сохраняется для минут и секунд при переходе через границы часа и минуты.
Метод subtract изменяет момент времени, тогда как
diff используется для вычисления разницы между двумя
моментами без изменения исходных данных.
Пример subtract:
const a = moment('2026-01-10');
a.subtract(5, 'days');
Пример diff:
const a = moment('2026-01-10');
const b = moment('2026-01-05');
a.diff(b, 'days'); // 5
Ключевое различие заключается в том, что diff возвращает
числовой результат, а subtract трансформирует объект.
Передача отрицательных значений в subtract приводит к
фактическому сложению времени:
moment('2026-01-10').subtract(-5, 'days');
Эквивалентно:
moment('2026-01-10').add(5, 'days');
Такая особенность может использоваться, но снижает читаемость кода,
поэтому предпочтительнее применять add для положительных
сдвигов вперёд.
Операция вычитания часто используется перед форматированием результата:
moment()
.subtract(7, 'days')
.format('YYYY-MM-DD');
Также возможно комбинирование с локализацией:
moment()
.subtract(1, 'month')
.locale('ru')
.format('LL');
Цепочки позволяют строить сложные временные вычисления:
moment('2026-12-31T23:59:59')
.subtract(1, 'year')
.subtract(2, 'months')
.subtract(3, 'days')
.subtract(4, 'hours')
.format();
Такая запись интерпретируется последовательно, каждая операция применяется к результату предыдущей.
Порядок вычитания имеет значение, особенно при работе с календарными единицами:
moment('2026-03-31')
.subtract(1, 'month')
.subtract(10, 'days');
и
moment('2026-03-31')
.subtract(10, 'days')
.subtract(1, 'month');
могут дать разные результаты из-за особенностей нормализации дат при переходе между месяцами.
Объектный вариант позволяет задавать отрицательные и положительные смещения одновременно:
moment('2026-01-10').subtract({
days: 10,
hours: 5,
minutes: 30
});
При этом отсутствует необходимость множественных вызовов метода.
При работе с UTC-датами поведение аналогично, но все операции выполняются в универсальном времени:
moment.utc('2026-01-10T00:00:00').subtract(1, 'days');
Это исключает влияние локальных часовых поясов и переходов на летнее время.
Мелкие единицы времени позволяют выполнять точные вычисления:
moment().subtract(1500, 'milliseconds');
При этом форматирование результата может скрывать точность, если используется формат без миллисекунд.
Встроенный Date не предоставляет удобного метода
вычитания интервалов, что требует ручного расчёта:
const d = new Date();
d.setDate(d.getDate() - 5);
Moment.js унифицирует подобные операции через единый интерфейс
subtract, снижая вероятность ошибок при работе с
календарными вычислениями.
При вычитании больших интервалов возможны переполнения календарных значений:
Эти особенности обрабатываются внутренним движком Moment.js автоматически, однако результат может отличаться от наивных арифметических ожиданий.