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

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

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

Основной инструмент: встроенная функция ДобавитьМесяц

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

Посмотрим на базовый пример вызова функции:


ДатаНачала = '28.02.2017';
ДатаОкончания = ДобавитьМесяц(ДатаНачала, 1);
Сообщить("Результат: " + ДатаОкончания); // Вернет 28.03.2017

Почему функция ДобавитьМесяц может не работать?

Если при вызове функции результат оказывается пустым или возникает ошибка времени выполнения, проанализируем основные причины:

  1. Несоответствие типа данных: Встроенная функция ожидает на вход значение строго с типом Дата. Если значение получено из строкового поля ввода на форме диалога, из файла или текстовой таблицы, оно может иметь строковый тип ("28.02.2017" вместо '28.02.2017'). В 1С 7.7 неявное приведение строки к дате внутри функций не выполняется. Для проверки типа используем функцию ТипЗначенияСтр(), а для преобразования — конструктор Дата().
  2. Пустое значение даты: Если исходная переменная не инициализирована или равна '00.00.0000', результат работы функции также вернет пустую дату. Проверить это можно вызовом ПустоеЗначение().
  3. Конфликт имен переменных: Не рекомендуется называть переменные системными зарезервированными словами платформы (например, имя Дата). Это может приводить к конфликту идентификаторов и непредсказуемому поведению модуля. Используем осмысленные имена: ТекДата, ДатаНачала, ИсходнаяДата.

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


Если ТипЗначенияСтр(ВходноеЗначение) = "Строка" Тогда
    ТекДата = Дата(ВходноеЗначение);
Иначе
    ТекДата = ВходноеЗначение;
КонецЕсли;

Если ПустоеЗначение(ТекДата) = 0 Тогда
    СледДата = ДобавитьМесяц(ТекДата, 1);
КонецЕсли;

Краевые случаи и несимметричность при вычислении дат

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

  1. Усечение по длине месяца: Если в целевом месяце меньше дней, чем в исходном (например, переход с 31 января на февраль), платформа усекает результат до последнего дня месяца: ДобавитьМесяц('31.01.2017', 1) вернет 28.02.2017.
  2. Эффект несимметричности: Функция не сохраняет историю вычислений. Если к 31 января прибавить месяц, получится 28 февраля. Если же затем от полученного 28 февраля отнять один месяц (ДобавитьМесяц('28.02.2017', -1)), мы получим 28.01.2017, а не исходное 31 января.
  3. Конец месяца: Смещение с 28 февраля на один месяц вперед даст именно 28 марта, так как 28-е число существует в марте. Если по бизнес-логике требуется гарантированно попадать на конец следующего месяца, результат следует оборачивать в функцию КонМесяца().

Посмотрим на пример логики сохранения конца месяца:


Если ТекДата = КонМесяца(ТекДата) Тогда
    НоваяДата = КонМесяца(ДобавитьМесяц(ТекДата, 1));
Иначе
    НоваяДата = ДобавитьМесяц(ТекДата, 1);
КонецЕсли;

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

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

Вариант 1: Формирование цепочки интервалов со сдвигом от даты окончания

Разберем пример построения интервалов вида 28.02.2017 - 28.03.2017, 29.03.2017 - 29.04.2017:


ДатаНачИнтервала = '28.02.2017';
КоличествоПериодов = 3;

Для Счетчик = 1 По КоличествоПериодов Цикл
    ДатаКонИнтервала = ДобавитьМесяц(ДатаНачИнтервала, 1);
    Сообщить("Период: " + ДатаНачИнтервала + " - " + ДатаКонИнтервала);
    
    // Начало следующего интервала смещается на 1 день от конца текущего
    ДатаНачИнтервала = ДатаКонИнтервала + 1;
КонецЦикла;

Вариант 2: Формирование классических непрерывных месячных интервалов («день в день минус один день»)

Если требуется сформировать календарные интервалы без пересечений (например, с 15-го числа по 14-е число следующего месяца):


ДатаНачИнтервала = '01.02.2017';
КоличествоПериодов = 3;

Для Счетчик = 1 По КоличествоПериодов Цикл
    // Вычисляем конец интервала как дату через месяц минус один день
    ДатаКонИнтервала = ДобавитьМесяц(ДатаНачИнтервала, 1) - 1;
    Сообщить("Интервал: " + ДатаНачИнтервала + " - " + ДатаКонИнтервала);
    
    // Начало следующего периода — следующий день после окончания
    ДатаНачИнтервала = ДатаКонИнтервала + 1;
КонецЦикла;

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

← На главную