Разработка и Конфигурация · 10 мин
Как в 1С отнять один день от даты
Как в 1С отнять 1 день от даты: функция ДобавитьДень с отрицательным сдвигом, вычитание секунд, запрос ДОБАВИТЬКДАТЕ и типичные ошибки с границами периодов.
Задача отнять один день от даты возникает в 1С постоянно: при формировании отчёта «по вчерашний день», при расчёте даты окончания периода, при подборе документов за прошлые сутки. Встроенный язык 1С не имеет оператора «минус день» для типа Дата, поэтому начинающие разработчики часто пишут некорректный код вроде вычитания числа 1 и получают сдвиг на одну секунду вместо одних суток.
Правильных способов несколько: функция ДобавитьДень с отрицательным параметром, вычитание 86400 секунд, конструкция ДОБАВИТЬКДАТЕ в запросах и комбинация НачалоДня/КонецДня для работы с границами периодов. Каждый вариант имеет свою область применения, и выбор зависит от того, где выполняется операция — в коде модуля, в запросе или в выражении СКД.
Ниже разобраны все рабочие варианты с примерами кода, граничными случаями (переход через месяц и год, полночь, пустая дата) и типичными ошибками, которые приводят к сбоям в отчётах и обработках.
Способ 1. Функция ДобавитьДень с отрицательным сдвигом
Основной и самый читаемый способ — встроенная функция ДобавитьДень. Она принимает два параметра: исходную дату и количество дней. Чтобы отнять один день, второй параметр должен быть отрицательным.
ДатаВчера = ДобавитьДень(ТекущаяДата(), -1);
Функция корректно обрабатывает переходы через границы месяца и года: от 1 марта получится 28 или 29 февраля в зависимости от високосности, от 1 января — 31 декабря предыдущего года. Ручной разбор календаря не требуется.
Важная особенность: функция сохраняет время в дате. Если исходное значение было 15.03.2026 14:30:00, результатом будет 14.03.2026 14:30:00. Если нужно получить начало вчерашнего дня, оберните результат в НачалоДня:
НачалоВчера = НачалоДня(ДобавитьДень(ТекущаяДата(), -1));
Аналогично работает связка с КонецДня, когда нужна дата окончания предыдущего дня — это типовой приём при построении отчётов «по вчерашний день включительно».
// Отнять 1 день от произвольной даты
ДатаВчера = ДобавитьДень(ИсходнаяДата, -1);
// Начало вчерашнего дня
НачалоВчера = НачалоДня(ДобавитьДень(ТекущаяДата(), -1));
// Конец вчерашнего дня
КонецВчера = КонецДня(ДобавитьДень(ТекущаяДата(), -1));Способ 2. Вычитание секунд из даты
В 1С дата хранится с точностью до секунды, и операция «Дата минус Число» вычитает именно секунды. Поэтому отнять один день можно, вычтя 86400 — количество секунд в сутках:
ДатаВчера = ТекущаяДата() - 86400;
Этот способ работает так же корректно на границах месяцев и лет, как и ДобавитьДень, потому что платформа выполняет арифметику на внутреннем представлении даты, а не на календарных компонентах.
Минус подхода — читаемость: магическое число 86400 приходится комментировать, а при рефакторинге его легко спутать с другими константами. Для вычитания одного дня предпочтительнее ДобавитьДень, а арифметику секунд разумно оставить для сдвигов меньше суток (часы, минуты), где специальных функций нет.
Способ 3. Отнять день в запросе: ДОБАВИТЬКДАТЕ
Когда дата обрабатывается внутри запроса — например, нужно отобрать документы за предыдущий день или сравнить реквизит с датой минус сутки — код на встроенном языке недоступен. В языке запросов 1С есть функция ДОБАВИТЬКДАТЕ с тремя параметрами: дата, тип сдвига, величина.
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(&Дата, ДЕНЬ, -1) КАК ДатаВчера
Тип сдвига может быть СЕКУНДА, МИНУТА, ЧАС, ДЕНЬ, НЕДЕЛЯ, МЕСЯЦ, КВАРТАЛ, ГОД и другие. Отрицательное значение третьего параметра уходит в прошлое, положительное — в будущее.
Типовой сценарий — отбор документов за вчерашний день без передачи вычисленной даты параметром:
ВЫБРАТЬ
Реализация.Ссылка
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
Реализация.Дата МЕЖДУ НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&ТекущаяДата, ДЕНЬ, -1), ДЕНЬ)
И КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&ТекущаяДата, ДЕНЬ, -1), ДЕНЬ)
На практике чаще выгоднее вычислить нужную дату один раз в коде через ДобавитьДень и передать её в запрос параметром — так запрос проще и оптимизатору легче использовать индекс по дате. ДОБАВИТЬКДАТЕ оправдана, когда сдвиг должен быть частью логики запроса или выражения СКД.
Сравнение способов
Универсальный вариант для кода модулей. Читаемо, корректно на границах периодов. Не работает в запросах.
Подходит для кода, удобно для сдвигов меньше суток. Менее читаемо, требует комментария.
Единственный вариант внутри текста запроса и выражений СКД. Если сдвиг можно вычислить в коде — лучше передать параметром.
Типовая задача: границы периода «по вчерашний день»
Самая частая прикладная ситуация — отчёт или обработка, которые должны работать с данными по конец предыдущего дня. Здесь отнять один день недостаточно: нужно ещё правильно выставить время на конец дня, иначе документы за вчерашний вечер выпадут из выборки.
Правильная конструкция выглядит так:
ОкончаниеПериода = КонецДня(ДобавитьДень(ТекущаяДата(), -1));
КонецДня возвращает время 23:59:59, поэтому в условии запроса используйте сравнение «меньше или равно» либо оператор МЕЖДУ. Если вместо КонецДня взять НачалоДня, получите 00:00:00 вчерашнего дня — и в период попадёт только одна секунда суток.
Обратная ошибка — использовать КонецПериода с границей «Включая» или «Исключая» без явного приведения времени. Всегда явно оборачивайте дату в НачалоДня или КонецДня, чтобы поведение было предсказуемым независимо от того, какое время оказалось в исходном значении.
- 1Вычислите вчерашнюю дату: ДобавитьДень(ТекущаяДата(), -1)
- 2Приведите её к концу дня: КонецДня(...)
- 3Передайте результат в запрос параметром
- 4В условии используйте Дата <= &ОкончаниеПериода или МЕЖДУ
- 5Проверьте выборку на документе, проведённом вчера в 23:50
Граничные случаи и проверка результата
Переход через начало месяца и года обе функции — ДобавитьДень и вычитание секунд — выполняют корректно. Отдельная логика не нужна: от 01.01.2026 10:00:00 при вычитании дня получится 31.12.2026 10:00:00.
Особое внимание — пустой дате. В 1С пустая дата равна 01.01.0001 00:00:00. Вычитание из неё дня может дать неожиданное значение или ошибку в зависимости от контекста, а в запросе сравнение с такой датой почти всегда искажает выборку. Перед арифметикой проверяйте заполненность:
Если ЗначениеЗаполнено(ИсходнаяДата) Тогда
ДатаВчера = ДобавитьДень(ИсходнаяДата, -1);
КонецЕсли;
Ещё один нюанс — функции ТекущаяДата() и ТекущаяДатаСеанса(). На клиенте ТекущаяДата возвращает время компьютера пользователя, которое может отличаться от серверного. Если «вчерашний день» должен считаться единообразно для всех пользователей, вычисляйте его на сервере через ТекущаяДатаСеанса().
Как проверить результат
От 01.03 получается последний день февраля
Получается 00.03 или ошибка
Время исходной даты сохранено либо явно сброшено через НачалоДня/КонецДня
Время сброшено или сдвинуто непредсказуемо
В выборку попадают документы за весь вчерашний день, включая вечер
Поздние документы выпадают — значит, использовано НачалоДня вместо КонецДня
Перед вычитанием есть проверка ЗначениеЗаполнено
Арифметика выполняется над 01.01.0001
Типичные ошибки и как их избежать
Первая и самая массовая ошибка — вычитание единицы: Дата - 1. Код не выдаёт исключения, отчёт формируется, но граница смещена на секунду. Такие дефекты всплывают случайно, когда в выборку попадает или не попадает документ ровно на полуночи.
Вторая ошибка — ручной разбор даты на день, месяц и год с вычитанием из компонента дня. При дне, равном 1, получается нулевой или отрицательный день месяца, и дальнейшая сборка даты через функцию Дата() приводит к ошибке. Календарную арифметику всегда делегируйте платформе.
Третья группа ошибок связана с временем: разработчик отнимает день, но забывает, что в исходной дате стоит 09:15:00, и использует результат как границу периода. Документы вчерашнего дня после 09:15 теряются. Правило простое: для границ периодов всегда явно применяйте НачалоДня или КонецДня после сдвига.
Частые вопросы
Чем отличаются ДобавитьДень(Дата, -1) и Дата - 86400?
Результат одинаковый: обе операции сдвигают дату ровно на сутки назад и корректно проходят границы месяцев и лет. Разница в читаемости: ДобавитьДень сразу показывает намерение, а число 86400 нужно комментировать. Для сдвигов меньше суток (часы, минуты) специальных функций нет, поэтому там арифметика секунд — единственный вариант.
Как отнять один день в запросе 1С?
Используйте функцию ДОБАВИТЬКДАТЕ с отрицательным третьим параметром: ДОБАВИТЬКДАТЕ(&Дата, ДЕНЬ, -1). Если сдвиг можно вычислить в коде до выполнения запроса, предпочтительнее рассчитать дату через ДобавитьДень и передать её параметром — это упрощает запрос и помогает использовать индексы.
Почему Дата - 1 не отнимает день?
Потому что в арифметике дат 1С единица измерения — секунда. Выражение Дата - 1 возвращает дату на одну секунду раньше. Для сдвига на сутки нужно вычесть 86400 или использовать ДобавитьДень(Дата, -1).
Как получить конец вчерашнего дня для отчёта?
Комбинацией двух функций: КонецДня(ДобавитьДень(ТекущаяДата(), -1)). Результат — вчерашняя дата со временем 23:59:59. В условии запроса используйте сравнение «меньше или равно» или оператор МЕЖДУ, чтобы документы за весь день попали в выборку.
Что будет, если отнять день от 1 января?
И ДобавитьДень, и вычитание секунд корректно вернут 31 декабря предыдущего года с сохранением времени. Платформа сама обрабатывает переход через границу года, отдельный код для этого не нужен. Ошибки возникают только при ручном разборе даты на компоненты.
Нужно ли проверять дату перед вычитанием дня?
Да, если дата приходит из реквизита, который может быть не заполнен. Пустая дата в 1С — это 01.01.0001, и арифметика с ней даст бессмысленный результат или исказит отбор в запросе. Перед вычитанием добавьте проверку ЗначениеЗаполнено(Дата).
Что важно запомнить
Один день в 1С отнимают функцией ДобавитьДень(Дата, -1) в коде или ДОБАВИТЬКДАТЕ(Дата, ДЕНЬ, -1) в запросе. Вычитание единицы сдвигает дату на секунду, а не на сутки. Для границ периодов после сдвига всегда применяйте НачалоДня или КонецДня, а перед арифметикой проверяйте заполненность даты.