К статье
Практический материал

Разработка и Конфигурация · 9 мин

Как вычесть из даты год в 1С

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

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

Главная тонкость — календарная логика. Год не является фиксированным количеством дней: 365 или 366 в високосном году. Поэтому вычитание 365 дней через Дата - 31536000 секунд даёт сдвиг на один день в високосные периоды. Правильный инструмент — функция работы с месяцами, которая учитывает календарь.

Ниже разобраны оба способа на встроенном языке, вычитание года в языке запросов, обработка граничного случая 29 февраля, проверка результата и типичные ошибки, которые приводят к неверным датам в отчётах и документах.

Способ 1: функция ДобавитьМесяцКДате с отрицательным значением

Стандартный и рекомендуемый способ вычесть год из даты — передать в функцию ДобавитьМесяцКДате() отрицательное количество месяцев. Год — это 12 месяцев, поэтому для вычитания одного года передаётся значение -12:

ДатаГодНазад = ДобавитьМесяцКДате(ТекущаяДатаСеанса(), -12);

Функция работает по календарным правилам: она уменьшает год на единицу, сохраняя номер месяца и число, если такое число существует в целевом месяце. Например, из 15.03.2026 получится 15.03.2026, а из 31.10.2026 — 31.10.2026.

Если нужно вычесть несколько лет, умножьте количество лет на 12: для трёх лет передайте -36. Это удобно при расчёте периодов хранения, сроков исковой давности, дат начала отчётных периодов:

ДатаТриГодаНазад = ДобавитьМесяцКДате(ДатаДокумента, -3 * 12);
Порядок действий
  1. 1
    Определите исходную дату: реквизит документа, параметр отчёта или ТекущаяДатаСеанса()
  2. 2
    Вызовите ДобавитьМесяцКДате(ИсходнаяДата, -12) для вычитания одного года
  3. 3
    Для нескольких лет передайте -12 * КоличествоЛет
  4. 4
    Проверьте результат в отладчике или через Сообщить()
  5. 5
    Убедитесь, что исходная дата не пустая — иначе получите дату 01.01.0001 или ошибку логики

Способ 2: вычитание секунд — когда допустимо и почему опасно

В 1С дата хранится с точностью до секунды, и над датами работает арифметика: Дата - Число вычитает указанное количество секунд. Технически можно написать:

ДатаГодНазад = ТекущаяДатаСеанса() - 365  24  60 * 60;

Такой код вычитает 365 дней. Проблема очевидна: високосный год содержит 366 дней, и при пересечении 29 февраля результат сместится на один день. Для отчётных периодов, кадровых расчётов и договорных сроков такая ошибка недопустима.

Вычитание секунд допустимо только там, где важен именно фиксированный интервал, а не календарная дата: например, отсечение записей журнала старше N дней или расчёт таймаутов. Для «минус год» всегда используйте ДобавитьМесяцКДате().

Вычитание года в языке запросов 1С

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

ВЫБРАТЬ

ДОБАВИТЬКДАТЕ(&Дата, ГОД, -1) КАК ДатаГодНазад

Альтернатива — единица МЕСЯЦ со значением -12, результат идентичен. Функцию можно применять прямо в условиях отбора, например, выбрать документы за последний год:

ГДЕ

ТаблицаДокументов.Дата >= ДОБАВИТЬКДАТЕ(&ТекущаяДата, ГОД, -1)

Учтите: смещение должно быть целым числом или параметром целого типа. Передача вычисляемого выражения не всегда поддерживается в старых версиях платформы — надёжнее вычислить значение в коде и передать параметром.

bsl
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
|	ДОБАВИТЬКДАТЕ(&Дата, ГОД, -1) КАК ДатаГодНазад";
Запрос.УстановитьПараметр("Дата", ТекущаяДатаСеанса());
Результат = Запрос.Выполнить().Выгрузить();

Граничный случай: 29 февраля и конец месяца

Самый коварный сценарий — вычитание года из 29 февраля високосного года. Например, из 29.02.2026 при вычитании года целевой даты 29.02.2023 не существует. Функция ДобавитьМесяцКДате() в этом случае возвращает последний день целевого месяца — 28.02.2023. Это стандартное календарное поведение, и обычно оно именно то, что нужно.

Аналогично обрабатывается конец месяца: из 31.03.2026 при вычитании месяца получится 28.02.2026, а не 03.03.2026. Если бизнес-логика требует другого поведения (например, всегда первое число или строгое совпадение дня), реализуйте его явно: проверьте день исходной даты и скорректируйте результат через НачалоМесяца() или КонецМесяца().

Проверяйте этот сценарий вручную при тестировании: задайте исходную дату 29.02 високосного года и убедитесь, что дальнейшая логика (проведение документа, построение отчёта) корректно работает с 28 февраля.

Контрольные точки

Как проверить результат

Обычная дата, например 15.06.2026
Норма

Результат 15.06.2026 — тот же день и месяц, год минус один

Тревожный признак

Смещение на день или смена месяца — вероятно, использованы секунды

29 февраля високосного года
Норма

Получено 28 февраля невисокосного года

Тревожный признак

Ошибка выполнения или дата 01.03

Пустая исходная дата
Норма

Код явно обрабатывает пустую дату до вычисления

Тревожный признак

В расчёте участвует 01.01.0001 и портит отборы

Типичные ошибки при вычитании года

Первая распространённая ошибка — вычитание фиксированных 365 дней в секундах. Код работает «почти всегда», и сбой проявляется только раз в четыре года, поэтому дефект долго остаётся незамеченным. Вторая ошибка — попытка собрать дату вручную через Год(Дата) - 1 и Дата(Год, Месяц, День): для 29 февраля такой код выдаст ошибку или неверную дату, если не добавить отдельную обработку.

Третья ошибка — игнорирование пустой даты. Если реквизит не заполнен, ДобавитьМесяцКДате('00010101', -12) вернёт дату до начала отсчёта, и отборы в запросах начнут работать непредсказуемо. Всегда проверяйте ЗначениеЗаполнено(Дата) перед вычислением.

Типичные ошибки
01
Вычитание 31536000 секунд вместо ДобавитьМесяцКДате — сдвиг на день в високосные периоды
02
Ручная сборка Дата(Год(Д)-1, Месяц(Д), День(Д)) без обработки 29 февраля — ошибка исполнения
03
Отсутствие проверки пустой даты — в расчёт попадает 01.01.0001
04
Передача дробного смещения в ДОБАВИТЬКДАТЕ — функция требует целое число

Практические сценарии применения

Период отчёта «последний год»

Для отчёта за скользящий год установите начало периода как ДобавитьМесяцКДате(ТекущаяДатаСеанса(), -12), а конец — текущую дату. Если нужен целый предыдущий календарный год, комбинируйте с НачалоГода() и КонецГода(): начало — НачалоГода(ДобавитьМесяцКДате(Дата, -12)).

Срок действия договора и напоминания

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

Возраст и стаж

Для проверки «исполнилось ли 18 лет» сравните дату рождения с ДобавитьМесяцКДате(ТекущаяДатаСеанса(), -18*12): если дата рождения меньше или равна — возраст достигнут. Это надёжнее, чем деление разности дат на 365.

Маршрут решения

Как выбрать действие

Нужна календарная дата ровно год назад в кодеИспользуйте ДобавитьМесяцКДате(Дата, -12)
Нужно вычесть год внутри запроса или отбора СКДПрименяйте ДОБАВИТЬКДАТЕ(Дата, ГОД, -1)
Нужен фиксированный интервал в днях, а не календарный годДопустимо вычитание секунд, но задокументируйте это в коде
Исходная дата может быть 29 февраляПротестируйте этот случай отдельно и зафиксируйте ожидаемое поведение
Итог

Что важно запомнить

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

Частые вопросы

Можно ли вычесть год через ДобавитьКДате с параметром «Год»?

Во встроенном языке нет функции ДобавитьКДате — есть только ДобавитьМесяцКДате, поэтому год задаётся как 12 месяцев. Параметр ГОД существует только в языке запросов в функции ДОБАВИТЬКДАТЕ.

Что вернёт ДобавитьМесяцКДате для даты 29.02.2026 при вычитании года?

Функция вернёт 28.02.2023 — последний день февраля целевого года, поскольку 29 февраля в невисокосном году не существует. Это стандартное календарное поведение платформы.

Как вычесть год от даты в отчёте на СКД без кода?

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

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

Наиболее вероятная причина — вычитание 365 дней через секунды при пересечении високосного года. Замените расчёт на ДобавитьМесяцКДате(Дата, -12), и смещение исчезнет.

Как вычесть год из даты, которая может быть пустой?

Сначала проверьте заполненность: Если ЗначениеЗаполнено(Дата) Тогда ... КонецЕсли. Для пустой даты заранее определите поведение — пропуск расчёта, значение по умолчанию или сообщение пользователю.

Чем отличается вычитание ГОД и МЕСЯЦ -12 в запросе?

Результат одинаков: оба варианта смещают дату ровно на один календарный год. Вариант с ГОД читается нагляднее, вариант с МЕСЯЦ удобен, когда количество лет вычисляется и передаётся параметром.