Вычитание одного дня из даты в 1С:Предприятие — задача, с которой регулярно сталкиваются и бухгалтеры при формировании отчетов, и разработчики при написании обработок. Казалось бы, что может быть проще? Но в зависимости от контекста — работы с документами, регистрами или программным кодом — подходы кардинально отличаются. Ошибка в расчетах может привести к сбоям в отчетности, некорректному начислению зарплаты или нарушению логики бизнес-процессов.
В этой статье мы разберем 7 рабочих способов, как отнять 1 день в 1С 8.3 и 1С 8.2, включая встроенные функции, запросы, программный код на языке 1С и даже обходные пути для нестандартных ситуаций. Каждый метод проиллюстрирован реальными примерами кода, которые можно скопировать и адаптировать под свою конфигурацию. Особое внимание уделим типичным ошибкам, из-за которых даты "съезжают" на месяц или год, и покажем, как их избежать.
1. Стандартная функция ДобавитьМесяц() — почему она не всегда работает
Самый очевидный способ — использовать встроенную функцию ДобавитьМесяц() с отрицательным значением. Однако здесь кроется подвох: функция добавляет или вычитает целые месяцы, а не дни. Если вам нужно именно вычесть 24 часа, этот метод приведет к неожиданным результатам.
Пример некорректного использования:
ДатуОтнять = ДобавитьМесяц(ТекущаяДата(), -1); // Ошибка! Отнимет 1 месяц, а не 1 день
Что произойдет, если выполнить этот код 1 марта 2026 года? Результат будет 1 февраля 2026 — вместо ожидаемого 28 февраля. Для вычитания именно дня функция не подходит. Но ее можно адаптировать:
Если вам нужно вычесть ровно 1 календарный месяц (например, для расчета просроченной дебиторки), используйте ДобавитьМесяц(Дата, -1). Для дней — читайте дальше.
- ❌ Не работает для вычитания дней (только месяцы)
- ⚠️ Опасно при работе с концами месяцев (31 число → 28/29 февраля)
- ✅ Подходит для месячных периодов (квартальные отчеты, графики платежей)
2. Функция НачалоДня() + арифметика секунд
Самый универсальный и безопасный способ — использовать арифметику секунд. В 1С даты хранятся как количество секунд с 1 января 1970 года, поэтому вычитание 86400 секунд (24 часа) даст точный результат.
Пример кода:
ДатуОтнять = НачалоДня(ТекущаяДата()) - 86400; // 86400 секунд = 24 часа
Почему НачалоДня() обязательно? Без нее вычтутся ровно 24 часа от текущего времени, что может привести к сбою, если сейчас, например, 00:30. Функция обнуляет время до 00:00:00, гарантируя корректный результат.
⚠️ Внимание: В высокосные годы (например, 2026) 1 марта минус 1 день должно дать 29 февраля. Этот метод справится с задачей, а ДобавитьМесяц() — нет.
| Исходная дата | Метод ДобавитьМесяц(-1) |
Метод -86400 секунд |
Правильный результат |
|---|---|---|---|
| 01.03.2026 | 01.02.2026 | 29.02.2026 | 29.02.2026 |
| 31.01.2026 | 31.12.2023 | 30.01.2026 | 30.01.2026 |
| 01.01.2026 12:00:00 | 01.12.2023 | 31.12.2023 12:00:00 | 31.12.2023 12:00:00 |
3. Использование конструктора запросов
Если вычитание дня нужно выполнить в запросе 1С (например, для отбора документов за предыдущий день), используйте функцию ДОБАВИТЬКДАТЕ() с параметром "ДЕНЬ".
Пример запроса:
ВЫБРАТЬ
ДатаДокумента КАК ПредыдущийДень
ИЗ
Документ.РеализацияТоваровУслуг
ГДЕ
ДатаДокумента = ДОБАВИТЬКДАТЕ(&ТекущаяДата, "ДЕНЬ", -1)
Особенности метода:
- 📅 Работает напрямую в языке запросов (не требует программного кода)
- ⚡ Быстрее, чем обработка дат в цикле на встроенном языке
- 🔄 Поддерживает вычитание не только дней, но и недель, месяцев, лет
⚠️ Внимание: В старых версиях 1С 8.1 функция ДОБАВИТЬКДАТЕ() могла не поддерживать отрицательные значения. В 8.3.20+ проблем нет.
4. Функция ДобавитьДень() — самый простой способ
Начиная с версии 1С 8.3.10, появилась специализированная функция ДобавитьДень(), которая решает проблему "из коробки". Она учитывает високосные годы, переходы между месяцами и даже часовые пояса.
Синтаксис:
ДатуОтнять = ДобавитьДень(ТекущаяДата(), -1); // Отнимает ровно 1 календарный день
Преимущества метода:
- 🎯 100% точный результат для любых дат (включая 29 февраля)
- 📜 Короткий и читаемый код
- 🔧 Поддерживает дробные дни (например,
-1.5для 12 часов)
Ограничение: функция недоступна в 1С 8.2 и более ранних версиях. Для них используйте метод с секундами (раздел 2).
Убедитесь, что версия платформы 8.3.10 или новее|Проверьте наличие функции в синтакс-помощнике|Тестируйте на границах месяцев (31→30, 1 марта→28 февраля)|Учитывайте часовые пояса, если работаете с UTC-->
5. Вычитание дней в формате строки (для обмена данными)
Если дата хранится в строковом формате (например, при импорте из Excel или JSON), сначала преобразуйте ее в тип Дата, а затем применяйте любой из описанных методов.
Пример обработки строки:
СтрокаДаты = "2026-03-15";
Дату = Дата(СтрокаДаты); // Преобразуем строку в дату
ДатуОтнять = Дату - 86400; // Вычитаем день
Типичные форматы строк, которые может распознать 1С:
- 📅
"DD.MM.YYYY"(русский формат: "15.03.2026") - 📅
"YYYY-MM-DD"(международный: "2026-03-15") - 📅
"DDMMYY"(короткий: "150324")
⚠️ Внимание: Если строка содержит время (например, "15.03.2026 14:30"), функцияДата()обрежет его до 00:00:00. Для сохранения времени используйтеДатаВремя().
6. Вычитание рабочих дней (исключая выходные)
Если нужно отнять 1 рабочий день (пропуская субботу и воскресенье), стандартные функции не подойдут. Здесь требуется кастомный код с проверкой дня недели.
Пример функции для рабочих дней:
Функция ОтнятьРабочийДень(Дату)
Дату = НачалоДня(Дату) - 86400; // Отнимаем 1 день
Пока ДеньНедели(Дату) = 6 ИЛИ ДеньНедели(Дату) = 7 Цикл // 6=суббота, 7=воскресенье
Дату = Дату - 86400;
КонецЦикла;
Возврат Дату;
КонецФункции
Как это работает:
- Отнимаем 1 день от исходной даты.
- Проверяем, не попали ли мы на выходной (
ДеньНедели()возвращает 6 или 7). - Если попали — отнимаем еще дни, пока не дойдем до пятницы.
Что будет, если отнять рабочий день от понедельника?
Если исходная дата — понедельник (03.06.2026), функция вернет пятницу (31.05.2026), пропустив субботу и воскресенье.
Для учета праздничных дней (например, 1 мая) потребуется расширять функцию проверкой по календарю производственного календаря РФ.
7. Типичные ошибки и как их избежать
Даже опытные разработчики допускают ошибки при работе с датами в 1С. Вот самые распространенные:
- 🔴 Игнорирование времени: Если не использовать
НачалоДня(), вычитание может дать некорректный результат из-за текущего времени. Например, 01.03.2026 01:00 - 24 часа = 28.02.2026 01:00 (а не 28.02.2026 00:00). - 🔴 Путаница с месяцами: Использование
ДобавитьМесяц()вместоДобавитьДень()приводит к сбоям в отчетности. - 🔴 Неучет високосных лет: 29 февраля минус 1 день должно дать 28 февраля, а не 1 марта.
- 🔴 Работа со строками без преобразования: Попытка вычесть дни из строки (например,
"15.03.2026" - 1) приведет к ошибке типа.
Как тестировать код с датами:
- Проверяйте на границах месяцев (31→30, 1 марта→28 февраля).
- Тестируйте с временем (не только даты, но и
ДатаВремя). - Используйте производственный календарь для рабочих дней.
Всегда оборачивайте операции с датами в НачалоДня(), если вам важна именно календарная дата, а не временная метка.
FAQ: Частые вопросы по вычитанию дней в 1С
Можно ли отнять 1 день прямо в отборе документа?
Да, в отборе можно использовать выражение ДатаДокумента = ДОБАВИТЬКДАТЕ(ТекущаяДата(), "ДЕНЬ", -1). Это сработает и в пользовательском режиме (без программирования).
Почему при вычитании дня из 1 марта получаю 28 февраля, а не 1 февраля?
Это корректное поведение! 1 марта минус 1 день — это 28 февраля (или 29 в високосный год). Если вам нужно отнять месяц, используйте ДобавитьМесяц().
Как отнять 1 день в управляемых формах?
В управляемых формах используйте серверные функции. Например, в модуле формы:
&НаСервере
Процедура ОтнятьДеньНаСервере()
ДатуОтнять = ДобавитьДень(ТекущаяДата(), -1);
Сообщить(ДатуОтнять);
КонецПроцедуры
Есть ли разница между Дату - 86400 и ДобавитьДень(Дату, -1)?
По результату — нет (оба метода вернут одну и ту же дату). Но ДобавитьДень():
- Короче и читаемее;
- Учитывает часовые пояса (если они настроены в базе);
- Поддерживает дробные дни (например,
-0.5для 12 часов).
Для простых задач разницы нет.
Как отнять 1 день в мобильном приложении 1С?
В мобильной платформе 1С доступны те же функции: ДобавитьДень() или арифметика секунд. Пример:
ДатуОтнять = НачалоДня(ТекущаяДата()) - 86400;
Ограничение: в мобильных формах некоторые функции (например, ДеньНедели()) могут требовать серверного контекста.