Разработка и Конфигурация · 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) КАК МесяцНазад
Единица измерения указывается ключевым словом без кавычек: СЕКУНДА, МИНУТА, ЧАС, ДЕНЬ, НЕДЕЛЯ, МЕСЯЦ, КВАРТАЛ, ГОД. Величина может быть отрицательной — именно так выполняется вычитание.
Типовой сценарий — отбор документов за прошлый месяц относительно параметра. Для этого сочетайте ДОБАВИТЬКДАТЕ с функциями НАЧАЛОПЕРИОДА и КОНЕЦПЕРИОДА, чтобы получить точные границы интервала и не потерять документы на краях периода.
ВЫБРАТЬ
Документ.Ссылка
ИЗ
Документ.РеализацияТоваровУслуг КАК Документ
ГДЕ
Документ.Дата МЕЖДУ НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&Период, МЕСЯЦ, -1), МЕСЯЦ)
И КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&Период, МЕСЯЦ, -1), МЕСЯЦ)Практические сценарии
Период отчёта: прошлый месяц от текущей даты
Частая задача — сформировать отчёт за предыдущий календарный месяц. Границы вычисляются так:
ТекущаяДата = ТекущаяДатаСеанса();
НачалоПрошлогоМесяца = НачалоМесяца(ДобавитьМесяц(ТекущаяДата, -1));
КонецПрошлогоМесяца = КонецМесяца(ДобавитьМесяц(ТекущаяДата, -1));
Обратите внимание: КонецМесяца() возвращает время 23:59:59, что корректно для сравнений «меньше или равно», но в запросах с виртуальными таблицами регистров надёжнее передавать границу через объект Граница или использовать начало следующего периода со строгим неравенством.
Срок оплаты или отсрочка в документах
Если договор предусматривает оплату «через месяц после отгрузки», дата платежа вычисляется как ДобавитьМесяц(ДатаОтгрузки, 1), а контроль просрочки — сравнением текущей даты с этим значением. Для обратного расчёта (например, дата счёта за месяц до поставки) применяется отрицательное смещение.
Аналогичный период прошлого года в аналитике
Для сравнения «месяц к месяцу прошлого года» от текущей даты отнимают 12 месяцев: ДобавитьМесяц(ТекущаяДата, -12). Это корректнее, чем вычитание года через Год(Дата) - 1 с ручной сборкой даты, поскольку автоматически решается проблема 29 февраля високосного года.
Какой способ выбрать
Проверка результата перед использованием
Перед тем как встраивать расчёт в рабочий код, проверьте его на граничных датах. Минимальный набор для теста: 31 марта (переход на короткий февраль), 1 января (переход через год), 29 февраля високосного года и произвольная середина месяца.
Быстрее всего это сделать через команду «Выполнить» в консоли кода или в отладчике: выведите результат через Сообщить() и сверьте с ожиданием. Для запросов используйте консоль запросов с подстановкой конкретного значения параметра.
Дополнительно убедитесь, что исходное значение вообще заполнено. ДобавитьМесяц('00010101', -1) вернёт пустую дату или вызовет ошибку в зависимости от контекста, и такой результат, попав в условие отбора, молча исключит все данные из отчёта.
Как проверить результат
28 или 29 февраля в зависимости от високосности
Несуществующая дата, исключение или 31.02 в строковом виде
Декабрь предыдущего года
Нулевой месяц или тот же год
Явная проверка и понятное сообщение пользователю
Молча пустой отчёт или падение кода
Типичные ошибки и ограничения
Самая распространённая ошибка — вычитание фиксированного числа дней. Код Дата - 30*86400 на первый взгляд работает, но в феврале уходит на два месяца назад, а в длинных месяцах не достигает нужной даты. Второй частый дефект — ручная сборка даты через Дата(Год(Д), Месяц(Д) - 1, День(Д)): при январе функция Дата() получает нулевой месяц и вызывает исключение.
Ещё одна ловушка — смешение типов. Если значение пришло из формы или СКД как строка, функция не сработает. Перед вызовом убедитесь, что тип — именно Дата, при необходимости используйте ТипЗнч() для проверки.
Наконец, помните про нестандартные календари: ДобавитьМесяц работает только по григорианскому календарю. Если прикладная логика опирается на производственные календари и рабочие дни, смещение на месяц нужно дополнять проверкой через регистр календарных графиков.
Что важно запомнить
Вычитание месяца в 1С выполняется функцией ДобавитьМесяц с отрицательным параметром, в запросах — ДОБАВИТЬКДАТЕ с единицей МЕСЯЦ. Платформа сама обрабатывает границы года и короткие месяцы, но результат на 29–31 числах требует проверки. Арифметика в секундах для календарных месяцев не применяется.
Частые вопросы
Как отнять месяц от текущей даты?
Получите текущую дату через ТекущаяДатаСеанса() (на сервере) и передайте её в функцию: ДобавитьМесяц(ТекущаяДатаСеанса(), -1). Использовать ТекущаяДата() в серверном коде не рекомендуется — она возвращает время клиентского компьютера, которое может отличаться от серверного.
Как получить первое число прошлого месяца?
Скомбинируйте две функции: НачалоМесяца(ДобавитьМесяц(НужнаяДата, -1)). Сначала дата смещается на месяц назад, затем обрезается до 00:00:00 первого числа. Аналогично для последнего дня используется КонецМесяца().
Что вернёт ДобавитьМесяц для 31 числа, если в прошлом месяце 30 дней?
Функция вернёт последний день целевого месяца. Например, от 31 мая минус месяц — это 30 апреля. Платформа не выдаёт несуществующих дат и не генерирует ошибку в такой ситуации.
Можно ли отнять месяц в запросе без параметра?
Да, если дата уже хранится в поле выборки: ДОБАВИТЬКДАТЕ(Документ.Дата, МЕСЯЦ, -1). Параметр нужен только когда базовая дата передаётся извне. Величина смещения при этом может быть и выражением, и литералом.
Чем отличается вычитание месяца от вычитания 30 дней?
Вычитание месяца — календарная операция: 15 марта минус месяц — это всегда 15 февраля. Вычитание 30 дней — арифметика в секундах: результат зависит от длины конкретных месяцев и в феврале может уйти на январь. Для договорных и отчётных периодов почти всегда нужен календарный вариант.
Как проверить, что дата не пустая, перед вычитанием месяца?
Используйте функцию ЗначениеЗаполнено(Дата) или сравнение с пустой датой '00010101'. Если дата не заполнена, выведите понятное сообщение или задайте значение по умолчанию — иначе пустой результат незаметно исказит отборы и расчёты.