Работа с датами в 1С:Предприятие — одна из самых востребованных задач как для бухгалтеров, так и для программистов. Часто требуется сдвинуть дату на определённое количество месяцев: для расчёта сроков оплаты, планирования графиков, формирования отчётности или автоматизации бизнес-процессов. Однако простое сложение чисел здесь не работает — нужно учитывать разную продолжительность месяцев, високосные годы и даже особенности григорианского календаря.

В этой статье мы разберём 5 проверенных способов добавить месяц к дате в 1С 8.3 и 1С 7.7, от базовых функций платформы до программного кода с обработкой крайних случаев. Вы узнаете, как избежать ошибок при работе с последним днём месяца, как корректно обрабатывать отрицательные значения и какие нюансы важно учитывать при работе с периодическими данными. Материал будет полезен как начинающим пользователям, так и опытным разработчикам, которые хотят оптимизировать свои решения.

1. Базовый метод: функция ДобавитьМесяц()

Самый простой и надёжный способ сдвинуть дату на заданное количество месяцев — использовать встроенную функцию ДобавитьМесяц(). Она автоматически учитывает разную длину месяцев и корректно обрабатывает переходы через годовые границы.

Синтаксис функции:

ДобавитьМесяц(НачальнаяДата, КоличествоМесяцев)

Примеры использования:

  • 📅 Прибавить 1 месяц: ДобавитьМесяц(ТекущаяДата(), 1) → если сегодня 31 января, результат будет 28 февраля (или 29 в високосный год).
  • 🔙 Отнять 2 месяца: ДобавитьМесяц(ДатаДокумента, -2) → полезно для расчёта просроченных платежей.
  • 📆 Сдвинуть на 12 месяцев: ДобавитьМесяц('2023-12-15', 12) → вернёт 2026-12-15.

Особенности работы функции:

  • ⚠️ Если итоговая дата выходит за пределы месяца (например, 31 апреля), функция автоматически корректирует её до последнего дня (30 апреля).
  • ✅ Поддерживает отрицательные значения для вычитания месяцев.
  • 🔄 Работает как в 1С 8.3, так и в 1С 7.7 (с небольшими синтаксическими различиями).
💡

Если вам нужно сохранить последний день месяца при добавлении месяцев (например, 31.01 + 1 месяц = 28.02, но требуется 31.03), используйте комбинацию функций НачалоМесяца() и КонецМесяца().

2. Работа с датами через запросы 1С

В некоторых случаях удобнее добавлять месяцы непосредственно в тексте запроса, особенно если вы работаете с большими массивами данных в отчётах или обработках. Для этого в языке запросов предусмотрен оператор ДОБАВИТЬ К ДАТЕ.

Пример запроса для сдвига даты на 3 месяца:

ВЫБРАТЬ

ДатаДокумента КАК ИсходнаяДата,

ДОБАВИТЬ К ДАТЕ(ДатаДокумента, МЕСЯЦ, 3) КАК НоваяДата

ИЗ

Документ.РеализацияТоваровУслуг

Ключевые моменты:

  • 📊 Оператор ДОБАВИТЬ К ДАТЕ поддерживает не только месяцы, но и дни, годы, часы.
  • 🔍 В результатах запроса можно сразу использовать рассчитанные даты для фильтрации или группировки.
  • ⚡ Быстрее, чем программное добавление в цикле, при работе с тысячами записей.

Ограничения метода:

  • ❌ Не позволяет гибко обрабатывать крайние случаи (например, всегда переходить на последний день месяца).
  • 📉 В 1С 7.7 синтаксис запросов отличается — используйте функцию ДобавитьМесяц() прямо в тексте запроса.
📊 Какой способ добавления месяцев вы используете чаще?
Встроенную функцию ДобавитьМесяц
Запросы 1С
Программный код на встроенном языке
Другие методы

3. Программный код: гибкая обработка дат

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

Функция ДобавитьМесяцыСКоррекцией(НачальнаяДата, КоличествоМесяцев)

Если ТипЗнч(НачальнаяДата) <> Тип("Дата") Тогда

Возврат Неопределено;

КонецЕсли;

// Сохраняем день месяца

ДеньМесяца = День(НачальнаяДата);

// Получаем первый день месяца

ДатаНачало = НачалоМесяца(НачальнаяДата);

// Добавляем месяцы

НоваяДата = ДобавитьМесяц(ДатаНачало, КоличествоМесяцев);

// Пытаемся вернуть исходный день

Попытка

Результат = ДобавитьДень(НоваяДата, ДеньМесяца - 1);

Исключение

// Если день выходит за пределы месяца, берём последний день

Результат = КонецМесяца(НоваяДата);

КонецПопытки;

Возврат Результат;

КонецФункции

Преимущества этого подхода:

  • 🎯 Точно сохраняет день месяца, если он существует в целевом месяце (например, 30.01 + 1 месяц = 30.02, а не 28.02).
  • 🛡️ Корректно обрабатывает переходы через годовые границы.
  • 🔧 Легко модифицировать под специфические требования (например, пропускать выходные).
Как модифицировать функцию для рабочих дней?

Добавьте проверку через функцию ЭтоРабочийДень() в цикле, пока не найдёте ближайший рабочий день после расчётной даты.

Пример использования:

Сообщить(ДобавитьМесяцыСКоррекцией('2023-01-31', 1)); // Вернёт 28.02.2023 (или 29.02 в високосный год)

Сообщить(ДобавитьМесяцыСКоррекцией('2023-01-30', 1)); // Вернёт 30.02.2023 → автоматически скорректируется до 28.02

4. Обработка крайних случаев: последний день месяца

Одна из самых распространённых проблем при работе с датами — корректная обработка последнего дня месяца. Например, если к 31.01.2023 добавить 1 месяц, стандартная функция вернёт 28.02.2023, что не всегда устраивает бизнес-логику. Рассмотрим альтернативные подходы.

Способ 1: Всегда последний день месяца

Функция ДобавитьМесяцДоКонца(НачальнаяДата, КоличествоМесяцев)

Возврат КонецМесяца(ДобавитьМесяц(НачалоМесяца(НачальнаяДата), КоличествоМесяцев));

КонецФункции

Способ 2: Сохранить день, если он существует (уже реализовано в функции из предыдущего раздела).

Сравнение методов:

Метод Пример (31.01 + 1 месяц) Пример (15.01 + 1 месяц) Когда использовать
ДобавитьМесяц() 28.02 15.02 Стандартные случаи, когда важен календарный сдвиг
С коррекцией (наш код) 28.02 15.02 Когда нужно сохранить день, если он существует
КонецМесяца() 28.02 28.02 Когда всегда нужен последний день месяца
💡

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

5. Добавление месяцев в 1С 7.7: особенности

В 1С:Предприятие 7.7 подходы к работе с датами несколько отличаются от современной платформы. Здесь нет функции ДобавитьМесяц(), но есть альтернативные методы.

Способ 1: Через компоненты даты

Процедура ДобавитьМесяц77(ДатаНач, Месяцев)

Год = Год(ДатаНач);

Месяц = Месяц(ДатаНач) + Месяцев;

// Корректируем год и месяц

Пока Месяц > 12 Цикл

Месяц = Месяц - 12;

Год = Год + 1;

КонецЦикла;

Пока Месяц < 1 Цикл

Месяц = Месяц + 12;

Год = Год - 1;

КонецЦикла;

// Определяем последний день месяца

День = День(КонецМесяца(Дата(Год, Месяц, 1)));

ДатаРез = Дата(Год, Месяц, Миним(День(ДатаНач), День));

Возврат ДатаРез;

КонецПроцедуры

Способ 2: Через ОLE-объекты (если доступен)

В некоторых конфигурациях 1С 7.7 можно использовать VBScript через OLE:

OLE = СоздатьОбъект("ScriptControl");

OLE.Language = "VBScript";

ДатаРез = OLE.Eval("DateAdd(""m"", " + Месяцев + ", """ + Формат(ДатаНач, "ДЛФ=D") + """)");

Сделать резервную копию базы|Проверить совместимость с версией платформы|Тестировать на копии рабочей базы|Учесть особенности конфигурации-->

⚠️ Внимание: В 1С 7.7 отсутствует встроенная обработка високосных годов в функции КонецМесяца() для февраля. При работе с датами вручную всегда проверяйте результат для февраля 2020, 2026 и других високосных годов.

6. Практическое применение: примеры из бухгалтерии и кадров

Добавление месяцев к датам широко используется в типовых конфигурациях . Рассмотрим реальные примеры:

1. Расчёт сроков уплаты налогов

В 1С:Бухгалтерия часто требуется определить последний день месяца, следующего за отчётным периодом. Например, для декларации по НДС за 1 квартал 2023 года срок уплаты — 25 апреля 2023 года, но если 25 число выпадает на выходной, срок переносится. Код для расчёта:

ДатаСдачи = КонецМесяца(ДобавитьМесяц(НачалоМесяца(ДатаОкончанияКвартала), 1));

Если Не ЭтоРабочийДень(ДатаСдачи) Тогда

ДатаСдачи = СледующийРабочийДень(ДатаСдачи);

КонецЕсли;

2. Графики отпусков в 1С:Зарплата и Управление Персоналом

При планировании отпусков нужно учитывать, что дата окончания отпуска должна быть рабочим днём. Пример кода для расчёта даты выхода:

ДатаНачалаОтпуска = '2023-06-01';

Длительность = 14; // дней

ДатаОкончания = ДобавитьДень(ДатаНачалаОтпуска, Длительность - 1);

Пока Не ЭтоРабочийДень(ДатаОкончания) Цикл

ДатаОкончания = ДобавитьДень(ДатаОкончания, 1);

КонецЦикла;

3. Планирование платежей по кредитам

В 1С:Управление торговлей или 1С:ERP часто требуется формировать график погашения кредита с ежемесячными платежами. Здесь важно, чтобы дата платежа не выпадала на выходной:

ДатаПервогоПлатежа = '2023-03-15';

КоличествоПлатежей = 12;

Для Сч = 1 По КоличествоПлатежей Цикл

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

Если Не ЭтоРабочийДень(ТекущаяДата) Тогда

ТекущаяДата = ПредыдущийРабочийДень(ТекущаяДата);

КонецЕсли;

ГрафикПлатежей.Добавить(ТекущаяДата);

КонецЦикла;

💡

Для проверки рабочих дней в 1С используйте функцию ЭтоРабочийДень() из стандартных библиотек или создайте собственную с учётом производственного календаря.

7. Частые ошибки и как их избежать

При работе с датами в даже опытные разработчики допускают ошибки. Разберём типичные проблемы и способы их решения.

Ошибка 1: Игнорирование високосных годов

Если вы вручную рассчитываете даты, не поленитесь проверить обработку февраля. Например, этот код ошибочно вернёт 28.02.2020 вместо 29.02.2020:

// НЕПРАВИЛЬНО!

НоваяДата = Дата(2020, 2, 28);

Решение: всегда используйте КонецМесяца() или встроенные функции.

Ошибка 2: Неучёт временных зон

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

ТекущаяДата = ТекущаяДатаСеанса(); // Берёт дату с учётом временной зоны пользователя

Ошибка 3: Прямое сложение чисел

Никогда не прибавляйте месяцы как числа к компонентам даты:

// НЕПРАВИЛЬНО!

НовыйМесяц = Месяц(ТекущаяДата) + 1; // Ошибка, если ТекущаяДата = декабрь!

Ошибка 4: Забывают про null-значения

Всегда проверяйте входные параметры на Неопределено или пустые даты:

Если ДатаДокумента = '00010101' Или Не ЗначениеЗаполнено(ДатаДокумента) Тогда

Возврат Неопределено;

КонецЕсли;

⚠️ Внимание: В 1С 8.3 пустая дата может быть представлена как '0001-01-01' или Неопределено. Всегда проверяйте оба варианта, если работаете с пользовательским вводом.

FAQ: Ответы на частые вопросы

Как добавить месяц к дате в отчёте 1С без программирования?

В большинстве стандартных отчётов (например, в 1С:Бухгалтерия) можно использовать пользовательские поля с формулами. Добавьте новое поле и введите выражение:

ДОБАВИТЬ К ДАТЕ(ДатаДокумента, МЕСЯЦ, 1)

Если отчёт не поддерживает такие формулы, создайте внешнюю обработку или модифицируйте отчёт в конфигураторе.

Почему функция ДобавитьМесяц() возвращает неверную дату для 31 числа?

Это не ошибка, а особенность работы функции. Она сохраняет порядковый номер дня в месяце. Например, 31 января — это 31-й день месяца, а в феврале максимум 28(29) дней. Поэтому функция возвращает последний день февраля.

Если вам нужно, чтобы 31.01 + 1 месяц = 31.03, используйте метод с коррекцией из раздела 4.

Как добавить месяц к дате в мобильном приложении 1С?

В мобильной платформе 1С:Предприятие доступны те же функции, что и в десктопной версии. Используйте:

НоваяДата = ДобавитьМесяц(ТекущаяДата(), 1);

Ограничения:

  • ⚠️ Некоторые сложные операции (например, работа с OLE) недоступны.
  • 📱 Производительность мобильных устройств ниже — избегайте тяжелых циклов.
Можно ли добавить месяц к дате в 1С:УТ 10.3?

Да, в 1С:Управление торговлей 10.3 (как и в других конфигурациях на платформе 8.2/8.3) доступна функция ДобавитьМесяц(). Пример для расчёта даты отгрузки:

ДатаОтгрузки = ДобавитьМесяц(ДатаЗаказа, 1);

Если ДеньНедели(ДатаОтгрузки) = 6 Тогда // Если суббота

ДатаОтгрузки = ДобавитьДень(ДатаОтгрузки, 2); // Переносим на понедельник

КонецЕсли;

Как добавить месяц к дате в запросе с группировкой?

Используйте оператор ДОБАВИТЬ К ДАТЕ прямо в разделе ГДЕ или ВЫБРАТЬ. Пример запроса для группировки документов по месяцам с учётом сдвига:

ВЫБРАТЬ

ДОБАВИТЬ К ДАТЕ(ДатаДокумента, МЕСЯЦ, 1) КАК МесяцОтгрузки,

СУММА(СуммаДокумента) КАК Итого

ИЗ

Документ.РеализацияТоваровУслуг

ГДЕ

ДатаДокумента МЕЖДУ &НачалоПериода И &КонецПериода

СГРУППИРОВАТЬ ПО

ДОБАВИТЬ К ДАТЕ(ДатаДокумента, МЕСЯЦ, 1)