Как правильно отнять полгода от текущей даты в 1С

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

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

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

Самый правильный и надежный способ вычитания месяцев во встроенном языке 1С — это использование функции ДобавитьМесяц. Эта функция специально разработана для корректной работы с календарем. Рассмотрим ее синтаксис: ДобавитьМесяц(ИсходнаяДата, КоличествоМесяцев). Если нам нужно отнять время, мы просто передаем отрицательное число.

Проанализируем пример кода:


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

Почему стоит использовать именно этот метод? Рассмотрим ситуацию, когда текущая дата — 31 августа. Если мы просто попытаемся отнять количество секунд, соответствующее среднему месяцу, мы можем получить некорректный результат. Функция ДобавитьМесяц «умная»: если в целевом месяце меньше дней, чем в исходном, она автоматически вернет последний день целевого месяца. Например, если от 31 августа отнять 6 месяцев, мы попадем в февраль, и система вернет 28 (или 29) число. Это критически важно для финансовой отчетности и кадрового учета.

Вычисления в запросах 1С

Часто задача стоит иначе: нужно отфильтровать данные в запросе, не подготавливая параметр заранее в коде. Для этого в языке запросов существует функция ДОБАВИТЬКДАТЕ. Посмотрим, как это выглядит в тексте запроса:


ВЫБРАТЬ
    Продажи.Ссылка,
    Продажи.Дата
ИЗ
    Документ.РеализацияТоваровУслуг КАК Продажи
ГДЕ
    Продажи.Дата > ДОБАВИТЬКДАТЕ(&ТекущаяДата, МЕСЯЦ, -6)

В данном примере мы перекладываем логику вычисления на сторону СУБД. Это удобно, так как позволяет динамически менять условия в зависимости от переданного параметра &ТекущаяДата. Функция ДОБАВИТЬКДАТЕ поддерживает различные типы периодов: СЕКУНДА, МИНУТА, ЧАС, ДЕНЬ, НЕДЕЛЯ, МЕСЯЦ, КВАРТАЛ, ГОД.

Метод вычитания секунд: риски и ошибки

Иногда начинающие программисты используют арифметический подход, переводя всё в секунды. В одном сутках ровно 86 400 секунд. Казалось бы, можно просто умножить это число на количество дней в полугодии. Однако здесь кроется ловушка. Разберем ситуацию: в полугодии может быть разное количество дней из-за разной длины месяцев и наличия високосного года (29 февраля). Если вы используете константу типа 180 * 86400, результат может «поплыть» на 1–3 дня.

Тем не менее, если вам нужно отнять дробный период (например, 6 месяцев и 14 дней), комбинация методов оправдана:


// Сначала отнимаем 6 полных месяцев, затем 14 дней в секундах
ИсходнаяДата = ТекущаяДата();
КолВоДней = 14;
Результат = ДобавитьМесяц(ИсходнаяДата, -6) - (КолВоДней * 86400);

Здесь 86400 — это количество секунд в сутках (24 часа * 60 минут * 60 секунд). Такой каскадный метод считается наиболее точным для сложных интервалов.

Приведение к началу периода

При работе с условием «ГДЕ х.Дата > ПараметрДата» крайне важно понимать, учитывается ли время. Если вы хотите выбрать документы за последние полгода, включая начало того дня, который был 6 месяцев назад, вам необходимо сбросить время в 00:00:00. Для этого используем функцию НачалоДня.

Рассмотрим комплексный пример:


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

Без использования НачалоДня, если текущее время 15:30, условие > отсечет документы, созданные утром того же дня полгода назад, что часто является логической ошибкой в отчетах.

Важность часовых поясов

Если ваша информационная база работает в клиент-серверном варианте и пользователи находятся в разных часовых поясах, функция ТекущаяДата() вернет время сервера. В таких случаях для корректного расчета «полгода назад относительно пользователя» рекомендуется использовать функцию ТекущаяДатаСеанса(). Это гарантирует, что для бухгалтера во Владивостоке и менеджера в Калининграде отчет за полгода сформируется корректно с учетом их локального времени.

Проверка на пустую дату

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


Если ЗначениеЗаполнено(ИсходнаяДата) Тогда
    ПараметрДата = ДобавитьМесяц(ИсходнаяДата, -6);
Иначе
    // Логика обработки пустой даты
КонецЕсли;

Подведем итоги

Для решения задачи вычитания полугода из даты мы выяснили следующее:

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

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

← На главную