Разработка и Конфигурация · 8 мин
Как отнять день от даты в 1С
Как отнять день от даты в 1С: функция ДобавитьКДате, вычитание секунд, работа с границами периода, учёт календаря и типичные ошибки разработчика.
Во встроенном языке 1С нет отдельной функции «отнять день», но задача решается несколькими штатными способами. Самый корректный — функция ДобавитьКДате() с отрицательным смещением: она понимает календарную логику и правильно обрабатывает переходы через границы месяца и года. Прямое вычитание числа из даты тоже работает, но ведёт себя иначе, и это часто становится источником ошибок.
Ниже разобраны основные приёмы: вычитание одного дня, работа с границами периода (конец предыдущего дня), особенности типов «Дата» и «Строка», а также типичные ошибки, из-за которых отчёт внезапно показывает не тот период. Примеры применимы как в толстом, так и в тонком клиенте, в том числе на сервере.
Способ 1: функция ДобавитьКДате с отрицательным смещением
Штатный и рекомендуемый способ отнять день — вызвать ДобавитьКДате() и передать отрицательное количество. Функция принимает три параметра: исходную дату, тип единицы (строкой) и величину смещения.
НоваяДата = ДобавитьКДате(ТекущаяДатаСеанса(), "День", -1);
// Если сегодня 01.03 — результат будет 28 или 29 февраля,
// в зависимости от високосности года
Допустимые значения второго параметра: "Секунда", "Минута", "Час", "День", "Неделя", "Месяц", "Квартал", "Год". Это позволяет тем же приёмом отнимать месяцы и годы, причём функция корректно обрабатывает разную длину месяцев: при вычитании месяца из 31 марта получится 28 или 29 февраля, а не несуществующая дата.
ВчерашняяДата = ДобавитьКДате(ТекущаяДатаСеанса(), "День", -1);Обратите внимание: функция сохраняет время в дате. Если исходная дата была 15.05.2026 14:30:00, результат будет 14.05.2026 14:30:00. Для получения начала вчерашнего дня комбинируйте её с НачалоДня() или КонецДня().
Способ 2: вычитание числа — почему это секунды, а не дни
В 1С дату можно вычитать как число, но платформа интерпретирует число как количество секунд. Выражение Дата - 1 вернёт ту же дату минус одну секунду, а не минус сутки. Чтобы отнять ровно один день арифметикой, нужно вычесть 86400 секунд (24 × 60 × 60).
Вчера = ТекущаяДатаСеанса() - 86400; // минус одни сутки
МинутаНазад = ТекущаяДатаСеанса() - 60; // минус одна минута
Этот способ работает быстро и коротко записывается, но у него есть ограничение: он оперирует абсолютным временем, а не календарём. Для отдельных суток разницы обычно нет, однако для месяцев и лет арифметика секунд неприменима вовсе — придётся всё равно использовать ДобавитьКДате(). Поэтому в прикладном коде предпочтителен первый способ как универсальный и самодокументируемый.
Как получить конец вчерашнего дня и начало прошлого периода
Самый частый прикладной сценарий — сформировать отчёт или выгрузку «по вчерашний день включительно». Здесь недостаточно просто отнять день: нужно ещё правильно установить время на границе периода.
ВчераНачало = НачалоДня(ДобавитьКДате(ТекущаяДатаСеанса(), "День", -1));
ВчераКонец = КонецДня(ДобавитьКДате(ТекущаяДатаСеанса(), "День", -1));
// ВчераКонец = 23:59:59 вчерашнего дня
Альтернативный приём для конца вчерашнего дня — взять начало сегодняшнего и отнять одну секунду:
ВчераКонец = НачалоДня(ТекущаяДатаСеанса()) - 1; // 23:59:59 вчера
Оба варианта дают одинаковый результат. При работе с запросами помните, что для виртуальных таблиц регистров границы лучше передавать через объект Граница с нужным видом включения, иначе движения ровно на границе могут попасть или не попасть в выборку не так, как ожидалось.
- 1Получите текущую дату сеанса: ТекущаяДатаСеанса()
- 2Отнимите день: ДобавитьКДате(Дата, "День", -1)
- 3Установите границы: НачалоДня() и КонецДня()
- 4Передайте значения в параметры запроса или отбора
- 5Проверьте результат на дате 1-го числа месяца
Отнимание дня в запросах и в СКД
В языке запросов 1С функции ДобавитьКДате нет. Там используется одноимённая по смыслу функция запроса ДОБАВИТЬКДАТЕ(Дата, Тип, Количество) с теми же типами периодов:
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(&ТекущаяДата, ДЕНЬ, -1) КАК ВчерашняяДата
Если отбор строится в СКД, вычислять дату удобнее на стороне кода до выполнения отчёта: рассчитайте вчерашнюю дату встроенным языком и передайте её в параметр компоновки. Это прозрачнее, чем выражения внутри схемы, и проще отлаживается.
Для выражений на языке СКД доступны функции ДобавитьКДате() и РазностьДат() в вычисляемых полях — синтаксис совпадает со встроенным языком.
Разница между ТекущаяДата и ТекущаяДатаСеанса при расчётах
При отнимании дня важно, от какой даты вы считаете. ТекущаяДата() на клиенте возвращает дату компьютера пользователя, которая может отличаться от серверной из-за часовых поясов или неверно выставленных часов. ТекущаяДатаСеанса() возвращает дату сервера с учётом часового пояса сеанса и предпочтительна в прикладной логике.
Если пользователь в другом часовом поясе запускает обработку около полуночи, «вчерашний день» по клиентской и серверной дате может оказаться разным. Для регламентных заданий и серверных процедур всегда используйте ТекущаяДатаСеанса().
Учёт рабочих и календарных дней
Отнять «один рабочий день» — это уже не арифметика дат, а работа с производственным календарём. Стандартные функции дат не знают о выходных и праздниках. В типовых конфигурациях для этого используются регистры календарных графиков (например, «Календарные графики» в БСП) и программные интерфейсы работы с ними.
Общий подход такой: в цикле отнимаете по одному календарному дню через ДобавитьКДате() и проверяете по регистру графика, рабочий ли это день. Счётчик уменьшается только на рабочие дни. Для разовых задач допустим перебор, для массовых расчётов лучше использовать готовые механизмы графиков работы, чтобы не дублировать логику праздничных переносов.
Проверка результата и отладка
После расчёта убедитесь, что результат соответствует ожиданиям, особенно на граничных датах: 1 января, 1 марта невисокосного года, 31-е число. Быстрая проверка в отладчике или через Сообщить():
Исходная = Дата(2026, 3, 1);
Результат = ДобавитьКДате(Исходная, "День", -1);
Сообщить(Результат); // 29.02.2026 0:00:00 — високосный год
Как проверить результат
Последний день предыдущего месяца
Тот же месяц или пустая дата
Сохранилось из исходной даты
Сброшено, если этого не требовалось
Включены документы до 23:59:59
Пропали документы за вторую половину дня
Что важно запомнить
Отнимайте дни через ДобавитьКДате(Дата, "День", -1) — это единственный способ, корректный на границах месяцев и лет. Арифметика с числами работает в секундах. Для периодов всегда задавайте границы через НачалоДня и КонецДня, а для серверной логики используйте ТекущаяДатаСеанса.
Частые вопросы
Как отнять несколько дней, а не один?
Передайте нужное отрицательное число третьим параметром: ДобавитьКДате(Дата, "День", -7) отнимет неделю. Ограничений на величину смещения в разумных пределах нет.
Что вернёт вычитание одной даты из другой?
Разность двух дат в 1С — это число секунд между ними, а не дата. Чтобы получить разницу в днях, разделите результат на 86400 или используйте функцию запроса РАЗНОСТЬДАТ с типом ДЕНЬ.
Работает ли ДобавитьКДате на тонком и веб-клиенте?
Да, функция доступна во всех режимах исполнения: толстый, тонкий, веб-клиент и сервер. Синтаксис и поведение идентичны.
Как отнять день в динамическом списке без изменения запроса?
Вычислите дату кодом в обработчике ПриСозданииНаСервере формы и установите её в параметр динамического списка через УстановитьПараметр. Сам текст запроса менять не потребуется, если параметр в нём уже предусмотрен.
Почему после отнимания дня дата стала пустой (01.01.0001)?
Такое происходит, если исходная дата была не заполнена или вы вычли смещение из минимальной даты. Перед расчётом проверяйте значение через ЗначениеЗаполнено(Дата) и при необходимости подставляйте дату по умолчанию.