Как отнять один месяц от даты в системе 1С:Предприятие

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

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

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

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

Рассмотрим простейший пример, когда нам нужно получить дату ровно на один месяц меньше текущей:


ТекущаяДата = ТекущаяДата(); // Например, 15.05.2023
ДатаМесяцНазад = ДобавитьМесяц(ТекущаяДата, -1);
// Результат будет: 15.04.2023

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

Особенности работы с концом месяца

Выясним причину, по которой многие начинающие разработчики сталкиваются с трудностями при работе с датами вроде 31 марта. Логика 1С при вычитании месяца строится на сохранении числа месяца, но с учетом максимально возможного количества дней в целевом периоде.

Проанализируем ситуацию на примере:


ИсходнаяДата = '20230331'; // 31 марта
Результат = ДобавитьМесяц(ИсходнаяДата, -1);
// Результат: 28.02.2023

Посмотрим на этот механизм подробнее. Поскольку в феврале 2023 года всего 28 дней, система не может вернуть "31 февраля". Вместо возникновения ошибки или переноса на март, 1С "приземляет" результат на последний день месяца. Это стандартное и ожидаемое поведение функции ДобавитьМесяц. Однако здесь кроется важный нюанс, который мы назовем «проблемой необратимости».

Важный момент: если вы отнимете месяц от 31 марта и получите 28 февраля, а затем прибавите к результату один месяц обратно, вы получите 28 марта, а не 31-е. Система "забывает", что исходное число было 31-м, так как промежуточный результат (28.02) уже зафиксировал это число как конечное.

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

Зачастую задачу вычитания месяца нужно решить не в коде, а непосредственно при выборке данных из базы. В языке запросов 1С функция ДобавитьМесяц недоступна, вместо нее используется функция ДОБАВИТЬКДАТЕ.

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


ВЫБРАТЬ
    ДОБАВИТЬКДАТЕ(&НачальнаяДата, МЕСЯЦ, -1) КАК ДатаПрошлогоМесяца

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

  1. Исходное поле или параметр типа Дата.
  2. Тип приращения (в нашем случае ключевое слово МЕСЯЦ).
  3. Величину приращения (-1 для вычитания).

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

Как гарантированно получить начало прошлого месяца

На практике программистам часто требуется не просто "отнять 30 дней", а получить первый день предыдущего календарного месяца относительно текущего. Для этого лучше всего использовать комбинацию функций НачалоМесяца и ДобавитьМесяц.

Разберем этот надежный метод:


// Предположим, сегодня 31 мая
ПрошлыйМесяц = ДобавитьМесяц(ТекущаяДата(), -1); // Получаем конец апреля или дату в апреле
НачалоПрошлогоМесяца = НачалоМесяца(ПрошлыйМесяц); // Получаем 01.04.2023

Такой подход позволяет избежать любых ошибок, связанных с разной длиной месяцев. Независимо от того, 28, 29, 30 или 31 день в текущем месяце, вы всегда попадете в нужный период.

Почему нельзя использовать вычитание секунд

Иногда возникает соблазн просто отнять от даты количество секунд, эквивалентное 30 дням (60 * 60 * 24 * 30). Проанализируем, почему это является грубой ошибкой:

Функция ДобавитьМесяц — это высокоуровневый инструмент, который инкапсулирует в себе всю календарную логику, избавляя разработчика от ручных проверок.

Обработка високосных лет

Посмотрим на пример с 29 февраля. Если ваша задача — получить дату ровно год назад, вы можете использовать ДобавитьМесяц с параметром -12.


ДатаВисокосная = '20240229'; // 29 февраля 2024 (високосный)
ГодНазад = ДобавитьМесяц(ДатаВисокосная, -12);
// Результат: 28.02.2023

Система корректно понимает, что в 2023 году 29-го числа нет, и возвращает 28 февраля. Это еще раз подтверждает, что использование встроенных функций — единственный верный путь для работы с календарными данными в 1С.

Применение в Системе компоновки данных (СКД)

В отчетах на базе СКД вы можете использовать те же функции в выражениях параметров или вычисляемых полей. Часто для удобства пользователей в СКД создаются параметры "НачалоПериода" и "КонецПериода".

Чтобы автоматически установить в параметре дату на месяц назад от текущей, в поле "Выражение" настроек СКД можно написать:

ДобавитьКДате(&ТекущаяДата, "Месяц", -1)

Это позволит отчету при открытии сразу предлагать пользователю данные за прошлый месяц, что значительно повышает удобство работы с программой.

Резюме

Подводя итог, мы видим, что задача "отнять месяц" в 1С решается просто, но требует понимания внутреннего устройства платформы. Мы рассмотрели основные методы:

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

Использование этих инструментов гарантирует корректность ваших расчетов в любой день года и для любого календарного периода.

← На главную