Разработка и Конфигурация · 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Определите исходную дату: реквизит документа, параметр отчёта или ТекущаяДатаСеанса()
- 2Вызовите ДобавитьМесяцКДате(ИсходнаяДата, -12) для вычитания одного года
- 3Для нескольких лет передайте -12 * КоличествоЛет
- 4Проверьте результат в отладчике или через Сообщить()
- 5Убедитесь, что исходная дата не пустая — иначе получите дату 01.01.0001 или ошибку логики
Способ 2: вычитание секунд — когда допустимо и почему опасно
В 1С дата хранится с точностью до секунды, и над датами работает арифметика: Дата - Число вычитает указанное количество секунд. Технически можно написать:
ДатаГодНазад = ТекущаяДатаСеанса() - 365 24 60 * 60;
Такой код вычитает 365 дней. Проблема очевидна: високосный год содержит 366 дней, и при пересечении 29 февраля результат сместится на один день. Для отчётных периодов, кадровых расчётов и договорных сроков такая ошибка недопустима.
Вычитание секунд допустимо только там, где важен именно фиксированный интервал, а не календарная дата: например, отсечение записей журнала старше N дней или расчёт таймаутов. Для «минус год» всегда используйте ДобавитьМесяцКДате().
Вычитание года в языке запросов 1С
В запросах даты обрабатываются функцией ДОБАВИТЬКДАТЕ. Она принимает три аргумента: дату, единицу измерения (СЕКУНДА, МИНУТА, ЧАС, ДЕНЬ, НЕДЕЛЯ, МЕСЯЦ, КВАРТАЛ, ГОД) и смещение. Для вычитания года смещение указывается отрицательным:
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(&Дата, ГОД, -1) КАК ДатаГодНазад
Альтернатива — единица МЕСЯЦ со значением -12, результат идентичен. Функцию можно применять прямо в условиях отбора, например, выбрать документы за последний год:
ГДЕ
ТаблицаДокументов.Дата >= ДОБАВИТЬКДАТЕ(&ТекущаяДата, ГОД, -1)
Учтите: смещение должно быть целым числом или параметром целого типа. Передача вычисляемого выражения не всегда поддерживается в старых версиях платформы — надёжнее вычислить значение в коде и передать параметром.
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| ДОБАВИТЬКДАТЕ(&Дата, ГОД, -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 — тот же день и месяц, год минус один
Смещение на день или смена месяца — вероятно, использованы секунды
Получено 28 февраля невисокосного года
Ошибка выполнения или дата 01.03
Код явно обрабатывает пустую дату до вычисления
В расчёте участвует 01.01.0001 и портит отборы
Типичные ошибки при вычитании года
Первая распространённая ошибка — вычитание фиксированных 365 дней в секундах. Код работает «почти всегда», и сбой проявляется только раз в четыре года, поэтому дефект долго остаётся незамеченным. Вторая ошибка — попытка собрать дату вручную через Год(Дата) - 1 и Дата(Год, Месяц, День): для 29 февраля такой код выдаст ошибку или неверную дату, если не добавить отдельную обработку.
Третья ошибка — игнорирование пустой даты. Если реквизит не заполнен, ДобавитьМесяцКДате('00010101', -12) вернёт дату до начала отсчёта, и отборы в запросах начнут работать непредсказуемо. Всегда проверяйте ЗначениеЗаполнено(Дата) перед вычислением.
Практические сценарии применения
Период отчёта «последний год»
Для отчёта за скользящий год установите начало периода как ДобавитьМесяцКДате(ТекущаяДатаСеанса(), -12), а конец — текущую дату. Если нужен целый предыдущий календарный год, комбинируйте с НачалоГода() и КонецГода(): начало — НачалоГода(ДобавитьМесяцКДате(Дата, -12)).
Срок действия договора и напоминания
Для уведомления за месяц до окончания годового договора вычислите дату напоминания как ДобавитьМесяцКДате(ДатаОкончания, -1). Не храните вычисляемые даты в базе без необходимости — рассчитывайте их в момент использования, чтобы не поддерживать актуальность при изменении исходных данных.
Возраст и стаж
Для проверки «исполнилось ли 18 лет» сравните дату рождения с ДобавитьМесяцКДате(ТекущаяДатаСеанса(), -18*12): если дата рождения меньше или равна — возраст достигнут. Это надёжнее, чем деление разности дат на 365.
Как выбрать действие
Что важно запомнить
Вычитание года из даты в 1С выполняется через ДобавитьМесяцКДате(Дата, -12) в коде и ДОБАВИТЬКДАТЕ(Дата, ГОД, -1) в запросах. Арифметика с секундами даёт ошибку на високосных годах. Всегда проверяйте пустые даты и тестируйте граничный случай 29 февраля.
Частые вопросы
Можно ли вычесть год через ДобавитьКДате с параметром «Год»?
Во встроенном языке нет функции ДобавитьКДате — есть только ДобавитьМесяцКДате, поэтому год задаётся как 12 месяцев. Параметр ГОД существует только в языке запросов в функции ДОБАВИТЬКДАТЕ.
Что вернёт ДобавитьМесяцКДате для даты 29.02.2026 при вычитании года?
Функция вернёт 28.02.2023 — последний день февраля целевого года, поскольку 29 февраля в невисокосном году не существует. Это стандартное календарное поведение платформы.
Как вычесть год от даты в отчёте на СКД без кода?
В выражении вычисляемого поля или в параметре отбора используйте язык выражений СКД, где доступна ДобавитьМесяцКДате(Дата, -12), либо функцию ДОБАВИТЬКДАТЕ на уровне текста запроса набора данных.
Почему после вычитания года дата сместилась на один день?
Наиболее вероятная причина — вычитание 365 дней через секунды при пересечении високосного года. Замените расчёт на ДобавитьМесяцКДате(Дата, -12), и смещение исчезнет.
Как вычесть год из даты, которая может быть пустой?
Сначала проверьте заполненность: Если ЗначениеЗаполнено(Дата) Тогда ... КонецЕсли. Для пустой даты заранее определите поведение — пропуск расчёта, значение по умолчанию или сообщение пользователю.
Чем отличается вычитание ГОД и МЕСЯЦ -12 в запросе?
Результат одинаков: оба варианта смещают дату ровно на один календарный год. Вариант с ГОД читается нагляднее, вариант с МЕСЯЦ удобен, когда количество лет вычисляется и передаётся параметром.