Разработка и Конфигурация · 10 мин
Как в 1С от текущей даты отнять дни, месяцы и годы
Как в 1С отнять от текущей даты дни, месяцы или годы: функции ТекущаяДата, ДобавитьМесяц, расчёт через секунды, запросы ДАТАВРЕМЯ и ДОБАВИТЬКДАТЕ.
Задача отнять от текущей даты несколько дней, месяцев или лет возникает в 1С постоянно: при расчёте сроков оплаты, фильтрации документов за период, проверке просроченной задолженности и формировании отчётов. Встроенный язык платформы не имеет оператора вычитания дат в привычном смысле — вместо этого используются функции работы с датой и арифметика через секунды.
Главное, что нужно понять сразу: тип «Дата» в 1С хранится с точностью до секунды, поэтому вычесть дни можно простым арифметическим выражением, а вот месяцы и годы так отнимать нельзя — из-за разной длины месяцев результат будет неточным. Для календарных сдвигов предусмотрена функция ДобавитьМесяц(), а в запросах — конструкция ДОБАВИТЬКДАТЕ.
Ниже разобраны все рабочие способы: на встроенном языке, в языке запросов, в схеме компоновки данных, а также типичные ошибки, которые приводят к неверным датам в документах и отчётах.
Получение текущей даты: ТекущаяДата и её особенности
Функция ТекущаяДата() возвращает дату и время компьютера, на котором выполняется код. Если код выполняется на сервере — это дата сервера 1С, если на клиенте — дата рабочей станции пользователя. В клиент-серверном режиме эти значения могут различаться, что иногда становится источником трудноуловимых ошибок.
В управляемых формах и тонком клиенте рекомендуется использовать ТекущаяДатаСеанса() — она всегда возвращает дату сервера и согласована между всеми пользователями сеанса. Для расчёта бизнес-сроков (оплата, отгрузка, просрочка) это предпочтительный вариант.
Пример получения базовой даты для дальнейших вычислений:
ТекДата = ТекущаяДатаСеанса(); // например, 15.03.2026 14:30:00
Как отнять дни, часы и минуты через секунды
Дата в 1С фактически является числом секунд, поэтому вычитание выполняется обычным оператором минус. Чтобы отнять N дней, нужно вычесть N × 86400 секунд (86400 = 24 × 60 × 60). Аналогично для часов — 3600 секунд, для минут — 60.
Примеры вычислений:
ТекДата = ТекущаяДатаСеанса();
// Отнять 7 дней
НеделяНазад = ТекДата - 7 * 86400;
// Отнять 30 дней
МесяцНазадПриблизительно = ТекДата - 30 * 86400;
// Отнять 12 часов
ПолсутокНазад = ТекДата - 12 * 3600;
Обратите внимание на комментарий «приблизительно» в третьем примере: 30 дней — это не календарный месяц. Если задача требует именно «тот же день предыдущего месяца», арифметика секунд не подходит — об этом следующий раздел.
Для удобства чтения кода константу часто выносят в переменную:
СекундВДне = 86400;
ДатаОплаты = ТекущаяДатаСеанса() - 10 * СекундВДне;
- 1Получите базовую дату: ТекущаяДатаСеанса()
- 2Умножьте количество дней на 86400
- 3Вычтите результат из базовой даты оператором минус
- 4При необходимости приведите результат к началу дня: НачалоДня(Результат)
- 5Проверьте результат выводом в сообщение или отладчиком
Как отнять месяцы и годы: функция ДобавитьМесяц
Для календарных сдвигов встроенный язык предоставляет функцию ДобавитьМесяц(Дата, КоличествоМесяцев). Несмотря на название, она умеет и отнимать: достаточно передать отрицательное число. Годы отнимаются как 12 месяцев.
ТекДата = ТекущаяДатаСеанса();
// Отнять 1 месяц
МесяцНазад = ДобавитьМесяц(ТекДата, -1);
// Отнять полгода
ПолгодаНазад = ДобавитьМесяц(ТекДата, -6);
// Отнять 2 года
ДваГодаНазад = ДобавитьМесяц(ТекДата, -24);
Важная особенность функции — обработка конца месяца. Если исходная дата 31 марта, то при вычитании одного месяца результат будет 28 (или 29) февраля, а не несуществующее «31 февраля». Функция автоматически берёт последний день целевого месяца. Это корректное календарное поведение, но если бизнес-логика требует другого — обработку нужно писать вручную.
Вычитание дат в запросах: ДОБАВИТЬКДАТЕ и РАЗНОСТЬДАТ
В языке запросов арифметика секунд недоступна, поэтому используется функция ДОБАВИТЬКДАТЕ(Дата, Тип, Количество). Тип задаёт единицу сдвига: СЕКУНДА, МИНУТА, ЧАС, ДЕНЬ, НЕДЕЛЯ, МЕСЯЦ, КВАРТАЛ, ГОД. Для вычитания передаётся отрицательное количество.
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(&ТекущаяДата, ДЕНЬ, -14) КАК ДвеНеделиНазад,
ДОБАВИТЬКДАТЕ(&ТекущаяДата, МЕСЯЦ, -3) КАК ТриМесяцаНазад
Типичный прикладной сценарий — отбор документов за последние N дней:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Реализация.Ссылка
|ИЗ
| Документ.РеализацияТоваровУслуг КАК Реализация
|ГДЕ
| Реализация.Дата >= ДОБАВИТЬКДАТЕ(&ТекущаяДата, ДЕНЬ, -30)";
Запрос.УстановитьПараметр("ТекущаяДата", ТекущаяДатаСеанса());
Если нужно не сдвинуть дату, а узнать, сколько дней прошло между двумя датами (например, дни просрочки), используйте РАЗНОСТЬДАТ(Дата1, Дата2, ДЕНЬ). В обычном коде аналог — простое вычитание дат, дающее разницу в секундах, которую затем делят на 86400.
// Разница между датами в днях
РазницаВДнях = (ТекущаяДатаСеанса() - ДатаДокумента) / 86400;
ДнейПросрочено = Цел(РазницаВДнях);Вычитание дат в СКД и настройках отчётов
В схеме компоновки данных вычисляемые поля работают на языке выражений СКД, где доступна функция ДобавитьМесяц(), а для сдвига на дни применяется вычитание секунд так же, как во встроенном языке. Например, в выражении вычисляемого поля: ДобавитьМесяц(&ТекущаяДата, -1).
На практике чаще достаточно стандартных периодов. В параметрах отчёта типа «СтандартныйПериод» пользователь выбирает «Прошлый месяц» или «Последние 7 дней», и платформа сама вычисляет границы от текущей даты. Это избавляет от ручных расчётов и ошибок с концами месяцев.
Если отчёт должен всегда строиться «за вчерашний день» или «за прошлый квартал» без вмешательства пользователя, задайте значения параметров в коде при формировании:
Параметры.УстановитьЗначениеПараметра("НачалоПериода",
НачалоДня(ТекущаяДатаСеанса() - 86400));
Параметры.УстановитьЗначениеПараметра("КонецПериода",
КонецДня(ТекущаяДатаСеанса() - 86400));
Способы отнять время от даты
Подходит для дней, часов, минут. Просто и быстро, но не для календарных месяцев
Единственный корректный способ отнять месяцы и годы в коде
Для отборов и вычислений на уровне СУБД, когда расчёт нужен прямо в запросе
Для отчётов, где пользователь сам выбирает интервал относительно текущей даты
Типичные ошибки при вычитании дат
Самая частая ошибка — вычитание месяцев через 30 × 86400. В феврале такой расчёт даёт смещение на 2 дня, а при длинных цепочках ошибка накапливается. Вторая распространённая проблема — игнорирование временной составляющей: ТекущаяДата() - 86400 возвращает вчерашнюю дату с текущим временем, и сравнение с датой документа без времени даст неожиданный результат.
Третья группа ошибок связана с границами периодов. Если отбор строится условием Дата <= КонецДня(ДатаОкончания), а разработчик передал дату без приведения к концу дня, документы последнего дня периода «выпадают» из отчёта. Всегда явно приводите границы через НачалоДня() и КонецДня().
Проверка результата и граничные случаи
После реализации расчёта проверьте его на граничных датах: первое и последнее число месяца, 29 февраля високосного года, переход через новый год. Например, вычитание одного дня из 1 января должно дать 31 декабря предыдущего года — платформа справляется с этим автоматически, но вашу обработку результата стоит проверить.
Для быстрой проверки выведите промежуточные значения:
Сообщить("База: " + ТекДата);
Сообщить("Минус 45 дней: " + (ТекДата - 45 * 86400));
Сообщить("Минус 3 месяца: " + ДобавитьМесяц(ТекДата, -3));
В отладчике тип «Дата» отображается в привычном формате, поэтому удобно ставить точку останова сразу после вычисления и сверять значение с календарём вручную.
Как проверить результат
Число месяца уменьшилось ровно на заданное количество дней
Смещение на лишний день или неверный месяц
Получен последний день предыдущего месяца
Ошибка или перескок через месяц
В выборку попали документы первого и последнего дня
Крайние дни периода пустые
Частые вопросы
Как отнять от даты один день в 1С?
Вычтите 86400 секунд: Вчера = ТекущаяДатаСеанса() - 86400;. Если нужна дата без времени, оберните результат в НачалоДня().
Как отнять месяц или год от текущей даты?
Используйте ДобавитьМесяц(ТекущаяДатаСеанса(), -1) для месяца и ДобавитьМесяц(ТекущаяДатаСеанса(), -12) для года. Арифметика секунд для месяцев не подходит из-за их разной длины.
Что вернёт вычитание одной даты из другой?
Число — разницу в секундах. Чтобы получить дни, разделите результат на 86400; для целого числа дней примените Цел(). В запросах для этого есть функция РАЗНОСТЬДАТ.
Почему ДобавитьМесяц(31 марта, -1) даёт 28 или 29 февраля?
Функция не может вернуть несуществующую дату, поэтому подставляет последний день целевого месяца. Это штатное поведение платформы, учитывайте его в бизнес-логике сроков.
Чем ТекущаяДата() отличается от ТекущаяДатаСеанса()?
ТекущаяДата() на клиенте берёт время компьютера пользователя, а ТекущаяДатаСеанса() — время сервера, единое для всех. Для расчёта сроков и просрочек надёжнее ТекущаяДатаСеанса().
Как в запросе отобрать документы за последние 7 дней?
Добавьте условие ГДЕ Документ.Дата >= ДОБАВИТЬКДАТЕ(&ТекущаяДата, ДЕНЬ, -7) и передайте параметр со значением ТекущаяДатаСеанса().
Что важно запомнить
Дни, часы и минуты отнимайте вычитанием секунд (день = 86400), месяцы и годы — только через ДобавитьМесяц с отрицательным аргументом, в запросах — через ДОБАВИТЬКДАТЕ. Для сравнений приводите даты к НачалоДня() или КонецДня() и используйте ТекущаяДатаСеанса().