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

Разработка и Конфигурация · 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. 1
    Получите базовую дату: ТекущаяДатаСеанса()
  2. 2
    Умножьте количество дней на 86400
  3. 3
    Вычтите результат из базовой даты оператором минус
  4. 4
    При необходимости приведите результат к началу дня: НачалоДня(Результат)
  5. 5
    Проверьте результат выводом в сообщение или отладчиком

Как отнять месяцы и годы: функция ДобавитьМесяц

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

ТекДата = ТекущаяДатаСеанса();

// Отнять 1 месяц

МесяцНазад = ДобавитьМесяц(ТекДата, -1);

// Отнять полгода

ПолгодаНазад = ДобавитьМесяц(ТекДата, -6);

// Отнять 2 года

ДваГодаНазад = ДобавитьМесяц(ТекДата, -24);

Важная особенность функции — обработка конца месяца. Если исходная дата 31 марта, то при вычитании одного месяца результат будет 28 (или 29) февраля, а не несуществующее «31 февраля». Функция автоматически берёт последний день целевого месяца. Это корректное календарное поведение, но если бизнес-логика требует другого — обработку нужно писать вручную.

Вычитание дат в запросах: ДОБАВИТЬКДАТЕ и РАЗНОСТЬДАТ

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

ВЫБРАТЬ

ДОБАВИТЬКДАТЕ(&ТекущаяДата, ДЕНЬ, -14) КАК ДвеНеделиНазад,

ДОБАВИТЬКДАТЕ(&ТекущаяДата, МЕСЯЦ, -3) КАК ТриМесяцаНазад

Типичный прикладной сценарий — отбор документов за последние N дней:

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Реализация.Ссылка

|ИЗ

| Документ.РеализацияТоваровУслуг КАК Реализация

|ГДЕ

| Реализация.Дата >= ДОБАВИТЬКДАТЕ(&ТекущаяДата, ДЕНЬ, -30)";

Запрос.УстановитьПараметр("ТекущаяДата", ТекущаяДатаСеанса());

Если нужно не сдвинуть дату, а узнать, сколько дней прошло между двумя датами (например, дни просрочки), используйте РАЗНОСТЬДАТ(Дата1, Дата2, ДЕНЬ). В обычном коде аналог — простое вычитание дат, дающее разницу в секундах, которую затем делят на 86400.

bsl
// Разница между датами в днях
РазницаВДнях = (ТекущаяДатаСеанса() - ДатаДокумента) / 86400;
ДнейПросрочено = Цел(РазницаВДнях);

Вычитание дат в СКД и настройках отчётов

В схеме компоновки данных вычисляемые поля работают на языке выражений СКД, где доступна функция ДобавитьМесяц(), а для сдвига на дни применяется вычитание секунд так же, как во встроенном языке. Например, в выражении вычисляемого поля: ДобавитьМесяц(&ТекущаяДата, -1).

На практике чаще достаточно стандартных периодов. В параметрах отчёта типа «СтандартныйПериод» пользователь выбирает «Прошлый месяц» или «Последние 7 дней», и платформа сама вычисляет границы от текущей даты. Это избавляет от ручных расчётов и ошибок с концами месяцев.

Если отчёт должен всегда строиться «за вчерашний день» или «за прошлый квартал» без вмешательства пользователя, задайте значения параметров в коде при формировании:

Параметры.УстановитьЗначениеПараметра("НачалоПериода",

НачалоДня(ТекущаяДатаСеанса() - 86400));

Параметры.УстановитьЗначениеПараметра("КонецПериода",

КонецДня(ТекущаяДатаСеанса() - 86400));

Способы отнять время от даты

Вычитание секунд

Подходит для дней, часов, минут. Просто и быстро, но не для календарных месяцев

ДобавитьМесяц с минусом

Единственный корректный способ отнять месяцы и годы в коде

ДОБАВИТЬКДАТЕ в запросе

Для отборов и вычислений на уровне СУБД, когда расчёт нужен прямо в запросе

Стандартный период

Для отчётов, где пользователь сам выбирает интервал относительно текущей даты

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

Самая частая ошибка — вычитание месяцев через 30 × 86400. В феврале такой расчёт даёт смещение на 2 дня, а при длинных цепочках ошибка накапливается. Вторая распространённая проблема — игнорирование временной составляющей: ТекущаяДата() - 86400 возвращает вчерашнюю дату с текущим временем, и сравнение с датой документа без времени даст неожиданный результат.

Третья группа ошибок связана с границами периодов. Если отбор строится условием Дата <= КонецДня(ДатаОкончания), а разработчик передал дату без приведения к концу дня, документы последнего дня периода «выпадают» из отчёта. Всегда явно приводите границы через НачалоДня() и КонецДня().

Типичные ошибки
01
Отнимать месяц как 30*86400 — результат расходится с календарём на 1–3 дня
02
Сравнивать дату со временем и дату без времени — условие срабатывает неверно
03
Использовать ТекущаяДата() на клиенте вместо ТекущаяДатаСеанса() — у пользователей с неверными часами расчёты разъезжаются
04
Забыть КонецДня() для верхней границы периода — теряются документы последнего дня
05
Отнимать дни у даты-строки без преобразования типа — ошибка выполнения

Проверка результата и граничные случаи

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

Для быстрой проверки выведите промежуточные значения:

Сообщить("База: " + ТекДата);

Сообщить("Минус 45 дней: " + (ТекДата - 45 * 86400));

Сообщить("Минус 3 месяца: " + ДобавитьМесяц(ТекДата, -3));

В отладчике тип «Дата» отображается в привычном формате, поэтому удобно ставить точку останова сразу после вычисления и сверять значение с календарём вручную.

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

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

Вычитание дней
Норма

Число месяца уменьшилось ровно на заданное количество дней

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

Смещение на лишний день или неверный месяц

Вычитание месяца из 31-го числа
Норма

Получен последний день предыдущего месяца

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

Ошибка или перескок через месяц

Отбор документов за период
Норма

В выборку попали документы первого и последнего дня

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

Крайние дни периода пустые

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

Как отнять от даты один день в 1С?

Вычтите 86400 секунд: Вчера = ТекущаяДатаСеанса() - 86400;. Если нужна дата без времени, оберните результат в НачалоДня().

Как отнять месяц или год от текущей даты?

Используйте ДобавитьМесяц(ТекущаяДатаСеанса(), -1) для месяца и ДобавитьМесяц(ТекущаяДатаСеанса(), -12) для года. Арифметика секунд для месяцев не подходит из-за их разной длины.

Что вернёт вычитание одной даты из другой?

Число — разницу в секундах. Чтобы получить дни, разделите результат на 86400; для целого числа дней примените Цел(). В запросах для этого есть функция РАЗНОСТЬДАТ.

Почему ДобавитьМесяц(31 марта, -1) даёт 28 или 29 февраля?

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

Чем ТекущаяДата() отличается от ТекущаяДатаСеанса()?

ТекущаяДата() на клиенте берёт время компьютера пользователя, а ТекущаяДатаСеанса() — время сервера, единое для всех. Для расчёта сроков и просрочек надёжнее ТекущаяДатаСеанса().

Как в запросе отобрать документы за последние 7 дней?

Добавьте условие ГДЕ Документ.Дата >= ДОБАВИТЬКДАТЕ(&ТекущаяДата, ДЕНЬ, -7) и передайте параметр со значением ТекущаяДатаСеанса().

Итог

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

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