К статье
Практический материал

Разработка и Конфигурация · 9 мин

Как в 1С от даты отнять месяц

Как в 1С отнять месяц от даты: функция ДобавитьМесяц с отрицательным значением, работа в запросах, нюансы конца месяца и типичные ошибки разработчиков.

Во встроенном языке 1С нет отдельной функции «отнять месяц», но задача решается штатно: функция ДобавитьМесяц() принимает отрицательное значение второго параметра. Вызов ДобавитьМесяц(Дата, -1) вернёт дату, смещённую ровно на один месяц назад, при этом платформа сама корректно обработает переход через год и разную длину месяцев.

Важно понимать, что простая арифметика с датами в 1С работает в секундах: выражение Дата - 30 * 86400 вычитает 30 суток, а не месяц. Такой подход даёт ошибку в один–три дня в зависимости от месяца и почти всегда является источником трудноуловимых дефектов в отчётах и регламентных расчётах.

Ниже разобраны синтаксис функции, поведение на границах месяцев, вариант для языка запросов, типовые сценарии (периоды отчётов, сроки оплаты, даты документов) и способы проверить результат до того, как код попадёт в рабочую базу.

Функция ДобавитьМесяц: синтаксис и принцип работы

Функция имеет два параметра: исходная дата и целое число месяцев, которое нужно прибавить. Для смещения назад передаётся отрицательное число:

ИсходнаяДата = Дата(2026, 3, 15);

МесяцНазад = ДобавитьМесяц(ИсходнаяДата, -1);

// Результат: 15.02.2026

Функция возвращает новое значение типа Дата, не изменяя исходную переменную. Время, если оно присутствует в дате (часы, минуты, секунды), сохраняется без изменений — смещается только календарная составляющая.

Отнять можно любое количество месяцев: ДобавитьМесяц(Дата, -3) вернёт дату квартал назад, ДобавитьМесяц(Дата, -12) — тот же день год назад. Платформа корректно обрабатывает переход через январь: ДобавитьМесяц(Дата(2026, 1, 20), -1) даст 20.12.2023, а не ошибку и не «нулевой» месяц.

Что происходит с датами в конце месяца

Главный нюанс — поведение, когда в целевом месяце нет соответствующего числа. Если от 31 марта отнять месяц, получится не «31 февраля» (такой даты не существует), а последний день февраля:

ДобавитьМесяц(Дата(2026, 3, 31), -1);

// Результат: 29.02.2026 (високосный год)

ДобавитьМесяц(Дата(2023, 3, 31), -1);

// Результат: 28.02.2023

Обратное смещение не всегда возвращает исходную дату. Цепочка «отнять месяц, потом прибавить месяц» для 31 марта даст 28 или 29 марта, а не 31-е число. Если в прикладной логике важно «прилипание» к концу месяца, используйте связку с функцией КонецМесяца():

КонецПрошлогоМесяца = КонецМесяца(ДобавитьМесяц(ИсходнаяДата, -1));

Вычитание месяца в языке запросов

В запросах функция называется иначе — ДОБАВИТЬКДАТЕ, и она принимает три параметра: дату, единицу измерения и величину смещения:

ВЫБРАТЬ

ДОБАВИТЬКДАТЕ(&ДатаОтчета, МЕСЯЦ, -1) КАК МесяцНазад

Единица измерения указывается ключевым словом без кавычек: СЕКУНДА, МИНУТА, ЧАС, ДЕНЬ, НЕДЕЛЯ, МЕСЯЦ, КВАРТАЛ, ГОД. Величина может быть отрицательной — именно так выполняется вычитание.

Типовой сценарий — отбор документов за прошлый месяц относительно параметра. Для этого сочетайте ДОБАВИТЬКДАТЕ с функциями НАЧАЛОПЕРИОДА и КОНЕЦПЕРИОДА, чтобы получить точные границы интервала и не потерять документы на краях периода.

bsl
ВЫБРАТЬ
	Документ.Ссылка
ИЗ
	Документ.РеализацияТоваровУслуг КАК Документ
ГДЕ
	Документ.Дата МЕЖДУ НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&Период, МЕСЯЦ, -1), МЕСЯЦ)
	И КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&Период, МЕСЯЦ, -1), МЕСЯЦ)

Практические сценарии

Период отчёта: прошлый месяц от текущей даты

Частая задача — сформировать отчёт за предыдущий календарный месяц. Границы вычисляются так:

ТекущаяДата = ТекущаяДатаСеанса();

НачалоПрошлогоМесяца = НачалоМесяца(ДобавитьМесяц(ТекущаяДата, -1));

КонецПрошлогоМесяца = КонецМесяца(ДобавитьМесяц(ТекущаяДата, -1));

Обратите внимание: КонецМесяца() возвращает время 23:59:59, что корректно для сравнений «меньше или равно», но в запросах с виртуальными таблицами регистров надёжнее передавать границу через объект Граница или использовать начало следующего периода со строгим неравенством.

Срок оплаты или отсрочка в документах

Если договор предусматривает оплату «через месяц после отгрузки», дата платежа вычисляется как ДобавитьМесяц(ДатаОтгрузки, 1), а контроль просрочки — сравнением текущей даты с этим значением. Для обратного расчёта (например, дата счёта за месяц до поставки) применяется отрицательное смещение.

Аналогичный период прошлого года в аналитике

Для сравнения «месяц к месяцу прошлого года» от текущей даты отнимают 12 месяцев: ДобавитьМесяц(ТекущаяДата, -12). Это корректнее, чем вычитание года через Год(Дата) - 1 с ручной сборкой даты, поскольку автоматически решается проблема 29 февраля високосного года.

Маршрут решения

Какой способ выбрать

Нужно сместить дату в коде модуляДобавитьМесяц(Дата, -N)
Смещение нужно прямо в запросе или СКДДОБАВИТЬКДАТЕ(Дата, МЕСЯЦ, -N)
Нужен не день-в-день, а граница прошлого месяцаНачалоМесяца() или КонецМесяца() вокруг ДобавитьМесяц
Требуется ровно N дней, а не календарный месяцАрифметика в секундах: Дата - N * 86400

Проверка результата перед использованием

Перед тем как встраивать расчёт в рабочий код, проверьте его на граничных датах. Минимальный набор для теста: 31 марта (переход на короткий февраль), 1 января (переход через год), 29 февраля високосного года и произвольная середина месяца.

Быстрее всего это сделать через команду «Выполнить» в консоли кода или в отладчике: выведите результат через Сообщить() и сверьте с ожиданием. Для запросов используйте консоль запросов с подстановкой конкретного значения параметра.

Дополнительно убедитесь, что исходное значение вообще заполнено. ДобавитьМесяц('00010101', -1) вернёт пустую дату или вызовет ошибку в зависимости от контекста, и такой результат, попав в условие отбора, молча исключит все данные из отчёта.

Контрольные точки

Как проверить результат

Дата 31.03 минус месяц
Норма

28 или 29 февраля в зависимости от високосности

Тревожный признак

Несуществующая дата, исключение или 31.02 в строковом виде

Дата в январе минус месяц
Норма

Декабрь предыдущего года

Тревожный признак

Нулевой месяц или тот же год

Пустая дата на входе
Норма

Явная проверка и понятное сообщение пользователю

Тревожный признак

Молча пустой отчёт или падение кода

Типичные ошибки и ограничения

Самая распространённая ошибка — вычитание фиксированного числа дней. Код Дата - 30*86400 на первый взгляд работает, но в феврале уходит на два месяца назад, а в длинных месяцах не достигает нужной даты. Второй частый дефект — ручная сборка даты через Дата(Год(Д), Месяц(Д) - 1, День(Д)): при январе функция Дата() получает нулевой месяц и вызывает исключение.

Ещё одна ловушка — смешение типов. Если значение пришло из формы или СКД как строка, функция не сработает. Перед вызовом убедитесь, что тип — именно Дата, при необходимости используйте ТипЗнч() для проверки.

Наконец, помните про нестандартные календари: ДобавитьМесяц работает только по григорианскому календарю. Если прикладная логика опирается на производственные календари и рабочие дни, смещение на месяц нужно дополнять проверкой через регистр календарных графиков.

Типичные ошибки
01
Вычитание 30 дней в секундах вместо календарного месяца — результат плывёт на 1–3 дня
02
Ручная сборка Дата(Год, Месяц-1, День) — исключение при переходе через январь
03
Ожидание обратимости: 31.03 минус месяц плюс месяц не возвращает 31.03
04
Отсутствие проверки на пустую дату — пустые отчёты без видимой ошибки
Итог

Что важно запомнить

Вычитание месяца в 1С выполняется функцией ДобавитьМесяц с отрицательным параметром, в запросах — ДОБАВИТЬКДАТЕ с единицей МЕСЯЦ. Платформа сама обрабатывает границы года и короткие месяцы, но результат на 29–31 числах требует проверки. Арифметика в секундах для календарных месяцев не применяется.

Частые вопросы

Как отнять месяц от текущей даты?

Получите текущую дату через ТекущаяДатаСеанса() (на сервере) и передайте её в функцию: ДобавитьМесяц(ТекущаяДатаСеанса(), -1). Использовать ТекущаяДата() в серверном коде не рекомендуется — она возвращает время клиентского компьютера, которое может отличаться от серверного.

Как получить первое число прошлого месяца?

Скомбинируйте две функции: НачалоМесяца(ДобавитьМесяц(НужнаяДата, -1)). Сначала дата смещается на месяц назад, затем обрезается до 00:00:00 первого числа. Аналогично для последнего дня используется КонецМесяца().

Что вернёт ДобавитьМесяц для 31 числа, если в прошлом месяце 30 дней?

Функция вернёт последний день целевого месяца. Например, от 31 мая минус месяц — это 30 апреля. Платформа не выдаёт несуществующих дат и не генерирует ошибку в такой ситуации.

Можно ли отнять месяц в запросе без параметра?

Да, если дата уже хранится в поле выборки: ДОБАВИТЬКДАТЕ(Документ.Дата, МЕСЯЦ, -1). Параметр нужен только когда базовая дата передаётся извне. Величина смещения при этом может быть и выражением, и литералом.

Чем отличается вычитание месяца от вычитания 30 дней?

Вычитание месяца — календарная операция: 15 марта минус месяц — это всегда 15 февраля. Вычитание 30 дней — арифметика в секундах: результат зависит от длины конкретных месяцев и в феврале может уйти на январь. Для договорных и отчётных периодов почти всегда нужен календарный вариант.

Как проверить, что дата не пустая, перед вычитанием месяца?

Используйте функцию ЗначениеЗаполнено(Дата) или сравнение с пустой датой '00010101'. Если дата не заполнена, выведите понятное сообщение или задайте значение по умолчанию — иначе пустой результат незаметно исказит отборы и расчёты.