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

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Работа с датами — одна из самых частых задач, с которыми сталкивается разработчик в системе 1С:Предприятие. Будь то расчет срока действия договора, определение даты следующего платежа или формирование периодических отчетов, нам постоянно требуется изменять исходную дату на определенный интервал. В этой статье мы подробно разберем, как правильно прибавлять месяцы к дате во встроенном языке, в запросах и в системе компоновки данных (СКД), а также проанализируем важные технические нюансы, о которых часто забывают новички.

Использование функции ДобавитьМесяц во встроенном языке

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

Проанализируем простейший пример кода:


// Определим исходную дату
ИсходнаяДата = ТекущаяДата(); // Например, 15.05.2023 10:00:00

// Прибавим к ней 3 месяца
НоваяДата = ДобавитьМесяц(ИсходнаяДата, 3);

// В результате получим 15.08.2023 10:00:00
Сообщить(НоваяДата);

Важно понимать, что функция ДобавитьМесяц() является универсальной. Если нам нужно не прибавить, а отнять месяцы, мы просто передаем во второй параметр отрицательное число. Давайте посмотрим на пример вычитания:


// Узнаем, какая дата была 6 месяцев назад
ПрошлаяДата = ДобавитьМесяц(ТекущаяДата(), -6);

Особенности логики конца месяца

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

Разберем конкретные ситуации, чтобы понять, как это работает на практике:

  1. Ситуация с 31 числом: Если мы прибавляем 1 месяц к дате "31 августа", то результатом будет "30 сентября", так как в сентябре всего 30 дней.
  2. Ситуация с февралем: Это самый наглядный пример. Если мы прибавим 1 месяц к "31 января", система вернет "28 февраля" (в обычном году) или "29 февраля" (в високосном).
  3. Сохранение времени: Обратите внимание, что время (часы, минуты и секунды) при использовании этой функции остается неизменным. Если исходная дата была "31.01.2023 23:59:59", то после добавления одного месяца мы получим "28.02.2023 23:59:59".

Эта логика позволяет избежать ошибок перескока через месяц, которые часто случаются при ручном расчете дат через прибавление секунд (например, Дата + 30 * 24 * 60 * 60), что является крайне неверным подходом в 1С.

Работа с датами в запросах 1С

В языке запросов 1С синтаксис функций отличается от встроенного языка. Для манипуляций с датами используется мощная функция ДОБАВИТЬКДАТЕ. В отличие от ДобавитьМесяц(), она позволяет работать с разными типами интервалов: секундами, минутами, часами, днями, неделями, месяцами, кварталами и годами.

Рассмотрим структуру функции в запросе:

ДОБАВИТЬКДАТЕ(&ИсходнаяДата, МЕСЯЦ, 1)

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

  1. Исходная дата: Поле или параметр типа Дата.
  2. Тип интервала: Ключевое слово (например, МЕСЯЦ, ДЕНЬ, ГОД).
  3. Количество: Числовое значение (может быть отрицательным).

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


ТекстЗапроса = "
|ВЫБРАТЬ
|    Договоры.Ссылка КАК Договор,
|    Договоры.ДатаЗаключения КАК ДатаНачала,
|    ДОБАВИТЬКДАТЕ(Договоры.ДатаЗаключения, МЕСЯЦ, 12) КАК ДатаОкончания
|ИЗ
|    Справочник.Договоры КАК Договоры";

Такой подход позволяет выполнять вычисления непосредственно на стороне сервера СУБД, что значительно повышает производительность системы при обработке больших массивов данных.

Особенности использования в СКД (Системе компоновки данных)

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

Обычно в выражениях СКД используют ДобавитьМесяц(), так как это более привычно для 1С-программистов. Например, если вам нужно рассчитать параметр "Конец периода" относительно "Начала периода", в схеме компоновки данных можно написать:

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

Система автоматически преобразует это выражение в соответствующую конструкцию при генерации запроса к базе данных.

Практические советы и сложные расчеты

Рассмотрим ситуацию, когда простой прибавки месяца недостаточно. Часто требуется получить начало или конец полученного периода. Для этого мы комбинируем функции работы с датами.

Пример: Получение начала следующего месяца

Если мы хотим, чтобы вне зависимости от текущего числа, результатом всегда было 1-е число следующего месяца, используем следующую конструкцию:


// Берем текущую дату, прибавляем месяц и округляем до начала месяца
НачалоСледующегоМесяца = НачалоМесяца(ДобавитьМесяц(ТекущаяДата(), 1));

Пример: Получение разницы в месяцах

Если ваша задача — не прибавить месяц, а вычислить, сколько полных месяцев прошло между двумя датами, помните, что во встроенном языке функции РазницаВМесяцах не существует. В запросах для этого есть функция РАЗНОСТЬДАТ(Дата1, Дата2, МЕСЯЦ).

Во встроенном языке расчет обычно выполняется следующим образом:


// Примерный расчет разницы в месяцах
РазницаВМесяцах = (Год(Дата2) - Год(Дата1)) * 12 + (Месяц(Дата2) - Месяц(Дата1));

Проверка типов данных

Прежде чем использовать функцию ДобавитьМесяц(), крайне важно убедиться, что переменная имеет тип Дата. Если вы передадите в функцию пустую дату ('00010101'), система отсчитает месяцы от начала нашей эры, что может привести к неожиданным результатам в логике программы. Рекомендуется всегда проверять значение на заполненность:


Если ЗначениеЗаполнено(ДатаДоговора) Тогда
    СрокДействия = ДобавитьМесяц(ДатаДоговора, СрокВМесяцах);
Иначе
    // Обработка ошибки или установка значения по умолчанию
КонецЕсли;

В современных конфигурациях, построенных на базе БСП (Библиотеки стандартных подсистем), существуют также общие модули (например, РаботаСДатами), которые позволяют вычислять даты с учетом производственного календаря. Это полезно, когда нужно прибавить не просто календарный месяц, а найти ближайший рабочий день через месяц, исключая праздники и выходные. Всегда проверяйте наличие таких функций в вашей конфигурации, прежде чем писать сложный велосипед по расчету рабочих дней.

← На главную