Работа с датами в 1С:Предприятие — одна из самых частых задач, с которыми сталкиваются и бухгалтеры при формировании отчетов, и программисты при написании обработок. Казалось бы, что может быть проще, чем отнять несколько дней от текущей даты? Но даже здесь есть подводные камни: неучет времени, ошибки при переходе через месяц или год, проблемы с нерабочими днями. Эта статья поможет разобраться во всех нюансах вычитания дней в 1С 8.3 и 8.2 — от базовых функций до профессиональных приемов для сложных расчетов.

Мы рассмотрим не только стандартные методы вроде Дата() + (-1), но и малоизвестные трюки с НачалоДня(), работой через ДобавитьМесяц() для корректного перехода через границы месяцев, а также автоматизацию вычитания рабочих дней с учетом праздников. Особое внимание уделим типичным ошибкам, из-за которых даты "съезжают" на сутки или вообще становятся невалидными. Готовые примеры кода вы сможете сразу использовать в своих конфигурациях.

Если вы никогда раньше не работали с датами в , начните с первого раздела — там объяснены основы, которые пригодятся даже для простых отчетов. Опытные разработчики могут сразу перейти к разделам про вычитание рабочих дней или расчеты с учетом времени, где разобраны нетривиальные кейсы. Не забывайте, что поведение функций может отличаться в разных версиях платформы — всегда тестируйте код на своей базе!

📊 Какой версии 1С вы пользуетесь?
8.3 (последняя)
8.2
7.7
Не знаю
Другая

1. Базовый метод: вычитание дней через арифметические операции

Самый простой способ отнять дни от даты в — использовать арифметические операции с типом Дата. Платформа автоматически преобразует числа в дни, поэтому достаточно написать:

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

ДатаМинус5Дней = ТекущаяДата - 5;

Этот код вернет дату, которая была 5 дней назад от сегодняшнего числа. Важно понимать, что здесь работает с полными сутками, игнорируя время. Например, если сегодня 10.05.2026 15:30:00, то результат будет 05.05.2026 00:00:00 — время сбросится на начало дня.

Арифметический метод удобен своей лаконичностью, но имеет ограничения:

  • ⚠️ Не учитывает рабочие/выходные дни (просто отнимает календарные сутки)
  • ⏰ Сбрасывает время до 00:00:00, что может быть критично для временных отчетов
  • 📅 Не корректирует даты при переходе через месяц/год (но это делает платформа автоматически)

Для большинства бухгалтерских задач (например, расчет сроков оплаты по договору) этого метода достаточно. Но если вам нужно сохранить время или учитывать только рабочие дни — читайте следующие разделы.

💡

Чтобы быстро проверить результат вычитания, используйте отладочную печать: Сообщить(ДатаМинус5Дней);. Это сэкономит время на поиск ошибок в коде.

2. Функция НачалоДня(): почему даты "съезжают" на сутки

Одна из самых распространенных ошибок при работе с датами в — игнорирование функции НачалоДня(). Дело в том, что платформа хранит дату и время в одном поле, и если вы не обнулите временную часть, результаты расчетов могут оказаться неожиданными.

Рассмотрим пример:

ТекущаяДатаСВременем = '20260510153000'; // 10 мая 2026, 15:30

ДатаМинус1День = ТекущаяДатаСВременем - 1;

Казалось бы, результат должен быть 09.05.2026. Но на самом деле мы получим 09.05.2026 15:30:00 — платформа вычла ровно 24 часа, а не один календарный день. Чтобы избежать этого, всегда обнуляйте время:

ДатаМинус1День = НачалоДня(ТекущаяДатаСВременем) - 1;

Теперь результат будет корректным: 09.05.2026 00:00:00. Эта особенность важна для:

  • 📊 Отчетов с группировкой по дням (чтобы не попадать в "вчерашние" данные)
  • 💰 Расчетов пени по дням просрочки (где важна точная дата, а не время)
  • 📦 Логистических задач (сроки доставки считаются в полных днях)
Что будет если не использовать НачалоДня() в отчетах?

При построении отчетов с группировкой по дням (например, продажи по дням) даты с временем могут попадать в неправильные группы. Например, запись от 10.05.2026 23:59 при вычитании 1 часа попадет в группировку 09.05.2026, искажая статистику.

3. Вычитание рабочих дней: учитываем выходные и праздники

В бизнес-задачах часто требуется вычесть не календарные, а именно рабочие дни (исключая субботу, воскресенье и праздники). Для этого в нет встроенной функции, поэтому придется написать свой алгоритм или использовать внешние обработки.

Вот базовый пример кода для вычитания рабочих дней (без учета праздников):

Функция ВычестьРабочиеДни(ИсходнаяДата, КоличествоДней)

Результат = ИсходнаяДата;

ТекущаяДата = ИсходнаяДата;

Для Сч = 1 По КоличествоДней Цикл

ТекущаяДата = ТекущаяДата - 1;

Пока ДеньНедели(ТекущаяДата) = 6 Или ДеньНедели(ТекущаяДата) = 7 Цикл // 6=суббота, 7=воскресенье

ТекущаяДата = ТекущаяДата - 1;

КонецЦикла;

Результат = ТекущаяДата;

КонецЦикла;

Возврат Результат;

КонецФункции

Для учета праздников нужно создать справочник с датами праздников и модифицировать цикл:

Если НайтиПоНаименованию(Справочники.Праздники, Формат(ТекущаяДата, "ДФ=dd.MM.yyyy")) <> Неопределено Тогда

ТекущаяДата = ТекущаяДата - 1;

КонецЕсли;

Готовые решения для рабочих дней:

  • 📁 Библиотека стандартных подсистем (БСП) содержит функции для работы с календарем
  • 🔧 Обработка "Календарь.epf" от (доступна на ИТС)
  • 🌐 Онлайн-сервисы для получения производственного календаря (можно интегрировать через HTTP-запросы)

Создать справочник "Праздники"|Заполнить датами официальных праздников|Проверить региональные особенности (например, переносы выходных)|Протестировать функцию на граничных случаях (пятница → понедельник)-->

Важно: производственный календарь в России меняется ежегодно! Перед использованием функции обязательно обновляйте список праздников (обычно публикуется правительством в ноябре-декабре предыдущего года).

4. Вычитание дней через ДобавитьМесяц(): когда это нужно

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

  1. Когда нужно вычесть дни с учетом конца месяца (например, отнять 3 дня от 31 января)
  2. Когда требуется сохранить последний день месяца при расчетах

Пример проблемы: если от 31.01.2026 отнять 3 дня арифметически, получим 28.01.2026. Но если нам нужно сохранить логику "последний день месяца", то результат должен быть 31.12.2026. Решение:

ИсходнаяДата = '20260131';

ДатаМинус3Дня = КонецМесяца(ДобавитьМесяц(ИсходнаяДата, -1)) - (3 - 1); // 31.12.2026

Таблица сравнения методов для граничных дат:

Исходная датаАрифметический методЧерез ДобавитьМесяц()Ожидаемый результат
31.01.202628.01.202631.12.202631.12.2026
28.02.202625.02.202631.01.202631.01.2026
30.04.202627.04.202631.03.202631.03.2026

Этот метод актуален для:

  • 📅 Расчета сроков действия договоров (если привязаны к концу месяца)
  • 💸 Начисления зарплаты за последние дни месяца
  • 📊 Формирования отчетов с группировкой по "закрытию месяца"
💡

Функция ДобавитьМесяц() сохраняет семантику "последнего дня месяца", что критично для финансовых расчетов, где важна точность до дня.

5. Работа с периодом: вычитание дней из начала/конца

В часто используются не отдельные даты, а периоды (интервалы с началом и концом). При вычитании дней из такого объекта нужно учитывать, какую именно границу вы модифицируете.

Пример кода для работы с периодами:

Период = НачалоДня('20260501') + КонецДня('20260510');

НовыйПериодНачало = НачалоПериода(Период) - 2; // Отнимаем 2 дня от начала

НовыйПериодКонец = КонецПериода(Период) - 2; // Отнимаем 2 дня от конца

Типичные ошибки при работе с периодами:

  • ❌ Путаница между НачалоПериода() и КонецПериода() — первая функция возвращает дату начала, вторая — дату окончания
  • ❌ Забывают обнулять время с помощью НачалоДня()/КонецДня(), из-за чего период "размывается"
  • ❌ Пытаются вычесть дни напрямую из переменной типа Период (нужно работать с границами отдельно)

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

ДействиеИсходный периодРезультат
Отнять 1 день от начала01.05.2026 — 10.05.202630.04.2026 — 10.05.2026
Отнять 1 день от конца01.05.2026 — 10.05.202601.05.2026 — 09.05.2026
Отнять 1 день от обеих границ01.05.2026 — 10.05.202630.04.202609.05.2026

Периоды активно используются в:

  • 📈 Отчетах с диапазоном дат (например, "продажи за период")
  • 🔄 Регламентных заданиях (расписание выполнения по датам)
  • 📂 Хранении исторических данных (версионность документов)
Период = НачалоДня(ТекущаяДата() - N) + КонецДня(ТекущаяДата() - 1);

Это создаст интервал длиной в N дней, заканчивающийся вчера.-->

6. Продвинутые техники: вычитание дней с учетом времени

Если в вашей задаче важно не только число, но и точное время (например, для логистических систем или систем мониторинга), стандартные методы не подойдут. Здесь нужно работать с секундами или использовать объекты МоментВремени.

Пример вычитания 24 часов (ровно одни сутки) с сохранением времени:

ДатаСВременем = '20260510153000'; // 10 мая, 15:30

ДатаМинус24Часа = ДатаСВременем - 86400; // 86400 секунд = 24 часа

Для более точных расчетов (например, вычитание 1 рабочего дня в 8 часов) можно использовать:

РабочийДеньВСекундах = 8 * 3600; // 8 часов

ДатаМинусРабочийДень = ДатаСВременем - РабочийДеньВСекундах;

Особенности работы с временем:

  • ⏱️ В время хранится в секундах с начала суток (00:00:00)
  • 🌍 Учитывайте часовой пояс, если работаете с распределенными системами
  • ⚡ Для высокоточных расчетов используйте МоментВремени() вместо типа Дата

Пример с МоментВремени():

Момент = МоментВремени(ТекущаяДата());

НовыйМомент = Момент - 86400; // Вычитаем ровно сутки

ДатаРезультат = Дата(НовыйМомент);

Когда нужно использовать МоментВремени вместо Дата?

Объект МоментВремени нужен в системах реального времени (мониторинг, логистика), где важна точность до секунды. Например, для расчета времени доставки с учетом часовых поясов или для синхронизации данных между филиалами в разных регионах.

7. Типичные ошибки и как их избежать

Даже опытные разработчики иногда допускают ошибки при работе с датами. Вот самые распространенные ловушки и способы их обхода:

⚠️ Внимание: Если вы вычитаете дни из даты в формате ГодМесяцДень (например, 20260510), а не используете тип Дата, платформа не сможет корректно обработать переход через месяц/год. Всегда преобразуйте строки в даты с помощью Дата(СтрокаДата).

Топ-5 ошибок и решения:

ОшибкаПричинаРешение
Дата становится невалидной (например, 32 января)Прямая манипуляция со строками вместо типа ДатаИспользуйте Дата() для преобразования
Результаты отличаются на сервере и клиентеРазные настройки региональных стандартовЯвно устанавливайте формат даты
Вычитание дней из НеопределеноНе проверена исходная дата на заполненностьДобавляйте проверку Если Дата = Неопределено Тогда...
"Съезд" даты на 1 день в отчетахНе учтено время (например, 23:59 попадает в предыдущий день)Применяйте НачалоДня()
Неправильный расчет рабочих днейНе учтены региональные праздники или переносыИспользуйте актуальный производственный календарь

Для отладки проблем с датами используйте эти приемы:

  • 🔍 Выводите промежуточные значения в отладочное окно: Сообщить(ТипЗнч(ВашаДата));
  • 📋 Проверяйте формат хранения даты: Сообщить(Формат(Дата, "ДФ=yyyyMMdd HH:mm:ss"));
  • 🛠️ Тестируйте граничные случаи: переход через месяц, високосные годы, даты около праздников
💡

90% ошибок с датами в 1С возникают из-за неявного приведения типов. Всегда явно преобразуйте строки в даты и наоборот, не полагаясь на автоматическое преобразование.

⚠️ Внимание: В версиях 1С:Предприятие 8.3.20+ изменилось поведение функции ДеньНедели() для дат до 1900 года. Если вы работаете с историческими данными, проверьте результаты этой функции в вашей версии платформы.

FAQ: Частые вопросы по вычитанию дней в 1С

Как вычесть дни из даты в запросе 1С?

В языке запросов для вычитания дней используйте функцию ДОБАВИТЬКДАТЕ() с отрицательным значением:

ВЫБРАТЬ

ДОБАВИТЬКДАТЕ(ТекущаяДата(), ДЕНЬ, -5) КАК ДатаМинус5Дней

ИЗ

Справочник.ЛюбойСправочник КАК ЛюбойСправочник

Обратите внимание, что в запросах не работает арифметика дат как в встроенном языке.

Почему при вычитании 1 дня из 1 марта получаю 28 февраля, а не 29?

Это связано с тем, что корректно обрабатывает переход через границы месяцев, но не учитывает високосные годы при "обратном" расчете. Чтобы получить 29 февраля, используйте:

ДатаРезультат = КонецМесяца(ДобавитьМесяц('20260301', -1)); // Вернет 28.02.2026 или 29.02.2026 в зависимости от года
Как вычесть дни из даты в форме 1С (например, в реквизите документа)?summary>

Для модификации даты прямо в форме:

  1. Создайте команду на форме с обработчиком
  2. В обработчике используйте код:
    Объект.ДатаДокумента = НачалоДня(Объект.ДатаДокумента) - КоличествоДней;
  3. Обновите форму: ОбновитьФорму();

Для удобства пользователей можно добавить кнопки "+1 день" и "-1 день" рядом с полем даты.

Можно ли вычесть дни из даты в отчете на СКД?

Да, в Системе компоновки данных для этого:

  1. Откройте настройки поля даты
  2. В выражении используйте: ДОБАВИТЬКДАТЕ([ВашеПоле], ДЕНЬ, -N)
  3. Либо создайте вычисляемый ресурс с аналогичной формулой

Пример для параметра отчета:

Параметры.ДатаНачала = ДОБАВИТЬКДАТЕ(ТекущаяДата(), ДЕНЬ, -7);

Как учитывать праздничные дни при вычитании?

Для учета праздников:

  1. Создайте справочник "ПраздничныеДни" с реквизитом Дата (тип Дата)
  2. Заполните его датами из производственного календаря
  3. Модифицируйте функцию вычитания:
    Пока НайтиПоПолю(Справочники.ПраздничныеДни, "Дата", ТекущаяДата) <> Неопределено Цикл
    

    ТекущаяДата = ТекущаяДата - 1;

    КонецЦикла;

Для автоматизации можно загружать календарь из внешних источников (например, с сайта правительства РФ).