Работа с датами в 1С:Предприятие — одна из самых частых задач при разработке отчётов, обработок или автоматизации бизнес-процессов. Казалось бы, что может быть проще, чем вычесть из текущей даты один день? Однако даже эта операция таит подводные камни: от особенностей синтаксиса разных версий платформы до нюансов работы с временными зонами и неполными датами. В этой статье разберём 5 способов отнять день от текущей даты — от базовых функций до программных конструкций для сложных сценариев.
Вы узнаете, как правильно использовать встроенные методы ДобавитьДень() и НачалоДня(), почему иногда результат отличается от ожидаемого, и как избежать ошибок при работе с датами в 1С 8.3 и 1С 8.2. А также рассмотрим практические примеры для бухгалтерских отчётов, складских документов и кадрового учёта, где точная работа с датами критически важна.
1. Базовый способ: функция ДобавитьДень() с отрицательным значением
Самый очевидный и рекомендуемый способ — использование встроенной функции ДобавитьДень() с передачей отрицательного числа. Этот метод работает во всех современных версиях платформы 1С:Предприятие 8 и гарантирует корректный результат даже с учётом високосных годов и переходов на зимнее/летнее время.
Пример кода:
ТекущаяДата = ТекущаяДата();
ВчерашняяДата = ДобавитьДень(ТекущаяДата, -1);
Особенности метода:
- 🔹 Работает как с полными датами (включая время), так и с датами без времени.
- 🔹 Автоматически корректирует месяц и год при переходе через границу (например, 1 января минус 1 день = 31 декабря предыдущего года).
- 🔹 В 1С 8.3.20+ поддерживает миллисекундную точность, если передать дату с временем.
⚠️ Внимание: Если вы работаете с датами в форматеДатаВремя(например, для журналов документов), результат может включать текущее время. Чтобы получить "чистую" дату без времени, оберните результат вНачалоДня():
ВчерашняяДата = НачалоДня(ДобавитьДень(ТекущаяДата(), -1));
2. Альтернативный подход: арифметика с датами через оператор -
Платформа 1С позволяет выполнять арифметические операции непосредственно с типами Дата, используя оператор вычитания. Этот способ лаконичнее, но требует понимания внутреннего представления дат в системе.
Пример:
ТекущаяДата = ТекущаяДата();
ВчерашняяДата = ТекущаяДата - 86400; // 86400 секунд = 1 день
Когда этот метод уместен:
- 📌 Для быстрых расчётов в обработках, где критична производительность.
- 📌 При работе с большими массивами дат (например, в циклах по календарю).
| Метод | Преимущества | Недостатки |
|---|---|---|
ДобавитьДень() |
Читаемый код, автоматическая корректировка дат | Незначительное снижение производительности при массовых операциях |
Оператор - |
Максимальная скорость выполнения | Менее наглядно, требует знания внутреннего формата дат |
⚠️ Внимание: При вычитании секунд учитывайте переходы на зимнее/летнее время — в эти дни сутки могут содержать 23 или 25 часов. Для бухгалтерских отчётов лучше использовать ДобавитьДень().
3. Работа с неполными датами и началом/концом дня
В 1С часто требуется получить не просто "вчерашнюю дату", а начало или конец предыдущих суток. Например, для фильтрации документов за прошлый день в отчётах. Здесь пригодятся комбинации функций НачалоДня(), КонецДня() и ДобавитьДень().
Примеры:
// Начало вчерашнего дня (00:00:00)
НачалоВчера = НачалоДня(ДобавитьДень(ТекущаяДата(), -1));
// Конец вчерашнего дня (23:59:59)
КонецВчера = КонецДня(ДобавитьДень(ТекущаяДата(), -1));
Типичные сценарии применения:
- 📊 Отбор документов за предыдущий рабочий день в отчётах по продажам.
- 📋 Автоматическое создание заданий на следующий день в кадровом учёте.
- 📈 Расчёт аналитики по сменам в производственных модулях.
Учтён ли переход на зимнее/летнее время?|Правильно ли обрабатываются граничные даты (1 января, 31 декабря)?|Совпадает ли результат с ручным расчётом для 3-5 тестовых дат?|Проведена ли валидация для високосных годов?-->
4. Вычитание дней в запросах 1С (Язык запросов)
При работе с языком запросов синтаксис отличается от встроенного языка. Здесь для манипуляций с датами используются специальные функции, такие как ДОБАВИТЬКДАТЕ() или арифметические операции с интервалами.
Пример запроса для выборки документов за вчерашний день:
ВЫБРАТЬ
Документ.Ссылка КАК Ссылка,
Документ.Дата КАК Дата
ИЗ
Документ.ЗаказПокупателя КАК Документ
ГДЕ
Документ.Дата МЕЖДУ
НАЧАЛОДНЯ(ДОБАВИТЬКДАТЕ(ТЕКУЩАЯДАТА(), ДЕНЬ, -1))
И
КОНЕЦДНЯ(ДОБАВИТЬКДАТЕ(ТЕКУЩАЯДАТА(), ДЕНЬ, -1));
Ключевые моменты:
- 🔧 В запросах нельзя использовать
ТекущаяДата()— толькоТЕКУЩАЯДАТА(). - 🔧 Функция
ДОБАВИТЬКДАТЕ()поддерживает добавление не только дней, но и месяцев, лет. - 🔧 Для фильтрации по датам всегда используйте
НАЧАЛОДНЯ()/КОНЕЦДНЯ(), чтобы избежать проблем с временем.
Что будет, если не использовать НАЧАЛОДНЯ/КОНЕЦДНЯ в запросах?
Без этих функций сравнение дат может давать неожиданные результаты из-за хранения времени. Например, документ от 23:59:59 "вчера" не попадёт в выборку, если фильтр установлен на "Дата = Вчера" без учёта времени. Это приводит к пропуску документов в отчётах и ошибкам в аналитике.
5. Программное вычитание дней с учётом рабочего календаря
В бизнес-задачах часто требуется отнять не календарный, а рабочий день (исключая выходные и праздники). Для этого в 1С используют Календарь или ПроизводственныйКалендарь.
Пример кода для получения предыдущего рабочего дня:
ПроизвКалендарь = Календари.ПроизводственныйКалендарь();
ТекущаяДата = ТекущаяДата();
ПредыдущийРабочийДень = ПроизвКалендарь.ПредыдущийРабочийДень(ТекущаяДата);
Где это применяется:
- 📅 Расчёт сроков доставки в модулях логистики.
- 💼 Автоматическое продление задач в системах управления проектами.
- 📉 Корректировка графиков платежей в бухгалтерии (если дата выпадает на выходной).
⚠️ Внимание: Производственный календарь в 1С может отличаться от государственного — например, в некоторых компаниях суббота является рабочим днём. Всегда уточняйте настройки календаря в конкретной базе.
Если в вашей конфигурации нет объекта "ПроизводственныйКалендарь", его можно создать самостоятельно или использовать внешнюю обработку с готовым календарём праздников России.
6. Обработка ошибок и особенности для разных версий 1С
Даже простая операция вычитания дня может давать сбои в зависимости от версии платформы или региональных настроек. Рассмотрим типичные проблемы и их решения.
Проблема 1: В 1С 8.2 функция ДобавитьДень() не поддерживает миллисекунды.
Решение: Используйте ДобавитьСекунд() для точной работы с временем.
Проблема 2: При вычитании дня из Неопределённо возникает ошибка.
Решение: Всегда проверяйте дату на заполненность:
Если НЕ ЗначениеЗаполнено(ИсходнаяДата) Тогда
Возврат Неопределено;
КонецЕсли;
Проблема 3: В облачных версиях 1С (например, 1С:Fresh) могут быть ограничения на программное изменение дат. Решение: Используйте серверные процедуры или проверяйте права доступа.
| Версия 1С | Особенности работы с датами | Рекомендации |
|---|---|---|
| 8.2 | Нет поддержки миллисекунд в ДобавитьДень() |
Используйте ДобавитьСекунд(Дата, -86400) |
| 8.3.6–8.3.19 | Поддержка миллисекунд, но возможны баги с временными зонами | Проверяйте результаты на граничных датах (переход на зимнее время) |
| 8.3.20+ | Полная поддержка временных зон и высокоточных операций | Можно использовать все описанные методы без ограничений |
Для критически важных расчётов (например, в бухгалтерских закрытиях) всегда тестируйте работу с датами на копии базы с реальными данными за прошлые периоды.
FAQ: Частые вопросы по работе с датами в 1С
Как отнять 3 дня от текущей даты?
Используйте функцию ДобавитьДень() с параметром -3:
ДатаМинусТриДня = ДобавитьДень(ТекущаяДата(), -3);
Или арифметический оператор:
ДатаМинусТриДня = ТекущаяДата() - (86400 * 3);
Почему при вычитании дня из 1 марта получаю 28 февраля, а не 29?
Это корректное поведение! Функция ДобавитьДень() учитывает реальную продолжительность месяцев. В невисокосный год февраль имеет 28 дней, поэтому 1 марта минус 1 день = 28 февраля. Для високосных годов результат будет 29 февраля.
Можно ли вычесть день из даты в формате строки?
Нет, сначала строку нужно преобразовать в тип Дата:
СтрокаДаты = "2026-12-31";
ДатаИзСтроки = Дата(СтрокаДаты);
Результат = ДобавитьДень(ДатаИзСтроки, -1);
Без преобразования возникнет ошибка несоответствия типов.
Как узнать, сколько дней между двумя датами?
Используйте функцию РазницаДней():
КоличествоДней = РазницаДней(Дата2, Дата1);
Если Дата2 позже Дата1, результат будет положительным.
Почему в отчёте не попадают документы за вчерашний день?
Скорее всего, в условии отбора не учтено время. Всегда используйте конструкцию:
ГДЕ Дата МЕЖДУ НачалоДня(Вчера) И КонецДня(Вчера)
Иначе документы с временем после 00:00 могут быть исключены.