Работа с датами — одна из самых частых задач, с которыми сталкивается разработчик в системе 1С:Предприятие. Будь то расчет срока действия договора, определение даты следующего платежа или формирование периодических отчетов, нам постоянно требуется изменять исходную дату на определенный интервал. В этой статье мы подробно разберем, как правильно прибавлять месяцы к дате во встроенном языке, в запросах и в системе компоновки данных (СКД), а также проанализируем важные технические нюансы, о которых часто забывают новички.
Для решения задачи во встроенном языке 1С предусмотрена стандартная функция ДобавитьМесяц(). Рассмотрим ее синтаксис и принцип работы. Функция принимает два параметра: исходную дату и количество месяцев, которое нужно добавить. Результатом выполнения функции всегда является новое значение типа Дата.
Проанализируем простейший пример кода:
// Определим исходную дату
ИсходнаяДата = ТекущаяДата(); // Например, 15.05.2023 10:00:00
// Прибавим к ней 3 месяца
НоваяДата = ДобавитьМесяц(ИсходнаяДата, 3);
// В результате получим 15.08.2023 10:00:00
Сообщить(НоваяДата);
Важно понимать, что функция ДобавитьМесяц() является универсальной. Если нам нужно не прибавить, а отнять месяцы, мы просто передаем во второй параметр отрицательное число. Давайте посмотрим на пример вычитания:
// Узнаем, какая дата была 6 месяцев назад
ПрошлаяДата = ДобавитьМесяц(ТекущаяДата(), -6);
Одним из самых критически важных аспектов работы функции ДобавитьМесяц() является алгоритм обработки дат, выпадающих на последние числа месяца. Платформа 1С реализует интеллектуальную логику: если в целевом месяце меньше дней, чем в исходном, система автоматически установит последнее число целевого месяца.
Разберем конкретные ситуации, чтобы понять, как это работает на практике:
Эта логика позволяет избежать ошибок перескока через месяц, которые часто случаются при ручном расчете дат через прибавление секунд (например, Дата + 30 * 24 * 60 * 60), что является крайне неверным подходом в 1С.
В языке запросов 1С синтаксис функций отличается от встроенного языка. Для манипуляций с датами используется мощная функция ДОБАВИТЬКДАТЕ. В отличие от ДобавитьМесяц(), она позволяет работать с разными типами интервалов: секундами, минутами, часами, днями, неделями, месяцами, кварталами и годами.
Рассмотрим структуру функции в запросе:
ДОБАВИТЬКДАТЕ(&ИсходнаяДата, МЕСЯЦ, 1)
Выясним назначение параметров:
Дата.МЕСЯЦ, ДЕНЬ, ГОД).Пример использования в тексте запроса:
ТекстЗапроса = "
|ВЫБРАТЬ
| Договоры.Ссылка КАК Договор,
| Договоры.ДатаЗаключения КАК ДатаНачала,
| ДОБАВИТЬКДАТЕ(Договоры.ДатаЗаключения, МЕСЯЦ, 12) КАК ДатаОкончания
|ИЗ
| Справочник.Договоры КАК Договоры";
Такой подход позволяет выполнять вычисления непосредственно на стороне сервера СУБД, что значительно повышает производительность системы при обработке больших массивов данных.
В Системе компоновки данных разработчики имеют больше гибкости. В выражениях полей или параметров СКД можно использовать как функцию встроенного языка ДобавитьМесяц(), так и функцию запросов ДобавитьКДате(). Проанализируем, какой вариант предпочтительнее.
Обычно в выражениях СКД используют ДобавитьМесяц(), так как это более привычно для 1С-программистов. Например, если вам нужно рассчитать параметр "Конец периода" относительно "Начала периода", в схеме компоновки данных можно написать:
ДобавитьМесяц(&НачалоПериода, 1)
Система автоматически преобразует это выражение в соответствующую конструкцию при генерации запроса к базе данных.
Рассмотрим ситуацию, когда простой прибавки месяца недостаточно. Часто требуется получить начало или конец полученного периода. Для этого мы комбинируем функции работы с датами.
Пример: Получение начала следующего месяца
Если мы хотим, чтобы вне зависимости от текущего числа, результатом всегда было 1-е число следующего месяца, используем следующую конструкцию:
// Берем текущую дату, прибавляем месяц и округляем до начала месяца
НачалоСледующегоМесяца = НачалоМесяца(ДобавитьМесяц(ТекущаяДата(), 1));
Пример: Получение разницы в месяцах
Если ваша задача — не прибавить месяц, а вычислить, сколько полных месяцев прошло между двумя датами, помните, что во встроенном языке функции РазницаВМесяцах не существует. В запросах для этого есть функция РАЗНОСТЬДАТ(Дата1, Дата2, МЕСЯЦ).
Во встроенном языке расчет обычно выполняется следующим образом:
// Примерный расчет разницы в месяцах
РазницаВМесяцах = (Год(Дата2) - Год(Дата1)) * 12 + (Месяц(Дата2) - Месяц(Дата1));
Прежде чем использовать функцию ДобавитьМесяц(), крайне важно убедиться, что переменная имеет тип Дата. Если вы передадите в функцию пустую дату ('00010101'), система отсчитает месяцы от начала нашей эры, что может привести к неожиданным результатам в логике программы. Рекомендуется всегда проверять значение на заполненность:
Если ЗначениеЗаполнено(ДатаДоговора) Тогда
СрокДействия = ДобавитьМесяц(ДатаДоговора, СрокВМесяцах);
Иначе
// Обработка ошибки или установка значения по умолчанию
КонецЕсли;
В современных конфигурациях, построенных на базе БСП (Библиотеки стандартных подсистем), существуют также общие модули (например, РаботаСДатами), которые позволяют вычислять даты с учетом производственного календаря. Это полезно, когда нужно прибавить не просто календарный месяц, а найти ближайший рабочий день через месяц, исключая праздники и выходные. Всегда проверяйте наличие таких функций в вашей конфигурации, прежде чем писать сложный велосипед по расчету рабочих дней.