Работа с датами в 1С:Предприятие — одна из самых востребованных задач при разработке отчётов, обработок и автоматизации бизнес-процессов. Чаще всего требуется посчитать разницу между двумя датами: для расчёта просрочек, сроков выполнения заказов, возраста клиентов или длительности проектов. Однако даже опытные программисты иногда сталкиваются с нюансами: как учесть только рабочие дни, как избежать ошибок при переходе на зимнее время, или как получить разницу не в днях, а в часах или месяцах.
В этой статье мы разберём 5 основных способов вычитания дат в 1С 8.3 и 8.2 — от элементарных функций до сложных алгоритмов с учётом производственного календаря. Вы узнаете, как:
- 📅 Использовать встроенные функции
Дата1 - Дата2иДеньГода()для базовых расчётов - ⏳ Получать разницу в часах, минутах и секундах с учётом временных зон
- 🏢 Вычитать даты с учётом рабочих дней и праздников (включая региональные)
- 🔍 Применять запросы 1С для массовой обработки дат в таблицах
- ⚙️ Писать универсальные функции для повторного использования в коде
Все примеры протестированы на актуальных релизах платформы 1С:Предприятие 8.3.22 и совместимы с большинством конфигураций (Бухгалтерия 3.0, УТ 11, ЗУП 3.1, КА 2.4). Если вы работаете со старыми версиями (8.1 или 8.0), некоторые методы могут требовать адаптации.
1. Базовое вычитание дат: функция разницы в днях
Самый простой способ получить разницу между двумя датами — использовать арифметическую операцию вычитания. Платформа 1С автоматически преобразует результат в количество дней (включая дробную часть для часов и минут).
Пример кода:
ДатаНачала = '2026-05-10 14:30:00';
ДатаОкончания = '2026-05-15 09:15:00';
РазницаВДнях = ДатаОкончания - ДатаНачала;
В переменной РазницаВДнях окажется значение 4.71875 (4 дня, 17 часов и 15 минут). Чтобы получить целое число дней, используйте функцию Цел():
Цел(РазницаВДнях); // Вернёт 4
⚠️ Внимание: При вычитании дат 1С не учитывает рабочие/выходные дни. Если вам нужна разница только по рабочим дням, используйте методы из раздела 4.
Этот метод подходит для:
- 📊 Расчёта сроков выполнения задач (например, время обработки заказа)
- 📈 Построения графиков по временным интервалам
- 🔄 Автоматического определения просроченных документов
| Функция | Описание | Пример результата |
|---|---|---|
Дата1 - Дата2 | Разница в днях (дробное число) | '2026-05-15' - '2026-05-10' → 5 |
Цел(Дата1 - Дата2) | Целое количество дней | Цел('2026-05-15 12:00' - '2026-05-10') → 5 |
Окр(Дата1 - Дата2, 2) | Округлённая разница (например, до часов) | Окр('2026-05-10 18:00' - '2026-05-10 09:00', 2) → 0.38 (9 часов) |
2. Разница в часах, минутах и секундах
Если вам нужна разница между датами с точностью до часов, минут или секунд, используйте функцию РазницаДат() или преобразуйте результат вычитания. Например, чтобы получить часы:
РазницаВЧасах = (ДатаОкончания - ДатаНачала) * 24;
Для минут и секунд используйте коэффициенты 1440 (минут в дне) и 86400 (секунд в дне) соответственно. Пример:
ДатаНачала = '2026-05-10 10:00:00';
ДатаОкончания = '2026-05-10 16:30:00';
// Разница в часах, минутах и секундах
Часы = (ДатаОкончания - ДатаНачала) * 24; // 6.5
Минуты = (ДатаОкончания - ДатаНачала) * 1440; // 390
Секунды = (ДатаОкончания - ДатаНачала) * 86400; // 23400
Для удобства вывода можно использовать функцию Формат():
Сообщить(Формат(Часы, "Ч=0.00; ЧД=0")); // Выведет "6.50"
Чтобы избежать ошибок при работе с временными зонами, всегда храните даты в формате ДатаВремя (а не Дата), даже если время не используется. Это гарантирует корректные расчёты при переходе на зимнее/летнее время.
Особенности работы с временем:
- ⏰ 1С учитывает временные зоны, если они настроены в информационной базе. Например, разница между
'2026-03-31 01:00:00'и'2026-03-31 03:00:00'в Москве составит 1 час (из-за перехода на летнее время). - ⚡ Для высокоточных расчётов (например, в логистике) используйте
Миллисекунды():
Миллисекунды = (ДатаОкончания - ДатаНачала) 86400 1000;
⚠️ Внимание: При работе с серверами 1С в разных временных зонах разница между датами может отличаться на ±N часов. Всегда синхронизируйте серверное время или используйте UTC.
3. Вычитание дат с учётом только рабочих дней
Для расчёта разницы с учётом рабочих дней (исключая выходные и праздники) в 1С есть два подхода:
- Использовать встроенный
Календарь(доступен в конфигурациях ЗУП, КА, ERP). - Создать собственную функцию с учётом производственного календаря.
Пример с использованием Календаря (для ЗУП 3.1):
Календарь = Календари.РабочийКалендарьОрганизации(Организация);
РазницаВРабочихДнях = Календарь.РазницаВДнях(ДатаНачала, ДатаОкончания);
Если в вашей конфигурации нет готового календаря, напишите универсальную функцию:
Функция РазницаВРабочихДнях(ДатаНачала, ДатаОкончания, МассивПраздников = Неопределено)
Если МассивПраздников = Неопределено Тогда
МассивПраздников = Новый Массив;
// Добавляем стандартные праздники (пример для России)
МассивПраздников.Добавить('2026-01-01'); // Новый год
МассивПраздников.Добавить('2026-05-01'); // Первомай
// ... остальные праздники
КонецЕсли;
ТекущаяДата = НачалоДня(ДатаНачала);
КонецДата = НачалоДня(ДатаОкончания);
РабочиеДни = 0;
Пока ТекущаяДата <= КонецДата Цикл
ДеньНедели = ДеньНедели(ТекущаяДата);
Если ДеньНедели <> 6 И ДеньНедели <> 7 И НЕ МассивПраздников.Найти(Формат(ТекущаяДата, "ДЛФ=Д")) Тогда
РабочиеДни = РабочиеДни + 1;
КонецЕсли;
ТекущаяДата = ТекущаяДата + 86400; // +1 день
КонецЦикла;
Возврат РабочиеДни;
КонецФункции;
Добавить все региональные праздники в массив|Учесть переносы выходных (если есть)|Проверить корректность временных зон|Обработать крайние случаи (например, ДатаНачала > ДатаОкончания)-->
Пример вызова функции:
Праздники = Новый Массив;
Праздники.Добавить('2026-05-09'); // День Победы
РабочиеДни = РазницаВРабочихДнях('2026-05-01', '2026-05-15', Праздники);
// Вернёт 9 (с 1 по 15 мая 2026 года 9 рабочих дней)
Для автоматизации можно загружать праздники из внешних источников (например, с сайта КонсультантПлюс) или использовать готовые обработки из Infostart.
4. Вычитание дат в запросах 1С
Если вам нужно посчитать разницу между датами для большого количества записей (например, в отчёте по просроченным платежам), используйте запросы 1С. Это значительно ускорит обработку данных.
Пример запроса для расчёта количества дней между датой документа и текущей датой:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ДокументСсылка КАК Ссылка,
| ДокументДата КАК ДатаДокумента,
| ТЕКУЩАЯДАТА() КАК ТекущаяДата,
| ДЕНЬГОДА(ТЕКУЩАЯДАТА()) - ДЕНЬГОДА(ДокументДата) КАК РазницаВДнях
|ИЗ
| Документ.ЗаказПокупателя КАК Документ
|ГДЕ
| Документ.ПометкаУдаления = ЛОЖЬ
| И Документ.Дата < ТЕКУЩАЯДАТА()";
Результат = Запрос.Выполнить();
Для более сложных расчётов (например, разницы в часах) используйте конструкцию РАЗНИЦАДАТ():
"ВЫБРАТЬ
| РАЗНИЦАДАТ(Документ.ДатаОплаты, Документ.ДатаОтгрузки, ЧАС) КАК РазницаВЧасах
|ИЗ
| Документ.РеализацияТоваровУслуг КАК Документ"
Особенности работы с датами в запросах:
- 🔹 Функция
РАЗНИЦАДАТ()поддерживает параметрыДЕНЬ,ЧАС,МИНУТА,СЕКУНДА. - 🔹 Для фильтрации по диапазону дат используйте
МЕЖДУ: - 🔹 В временных таблицах даты хранятся без учёта временной зоны — это может привести к ошибкам при сравнении.
Как ускорить запрос с датами?
Используйте индексы по полям с датами в регистрах и документах. Например, для таблицы Документ.ЗаказПокупателя создайте индекс по полю Дата. Это ускорит фильтрацию по диапазону дат в 10-100 раз.
| Функция запроса | Описание | Пример |
|---|---|---|
ТЕКУЩАЯДАТА() | Возвращает текущую дату и время на сервере | ГДЕ Дата < ТЕКУЩАЯДАТА() |
НАЧАЛОПЕРИОДА() | Возвращает начало дня/недели/месяца | НАЧАЛОПЕРИОДА(Дата, "МЕСЯЦ") |
ДОБАВИТЬКДАТЕ() | Прибавляет интервал к дате | ДОБАВИТЬКДАТЕ(Дата, ДЕНЬ, 7) |
РАЗНИЦАДАТ() | Разница между датами в заданных единицах | РАЗНИЦАДАТ(Дата2, Дата1, ЧАС) |
5. Учёт временных зон и летнего времени
Если ваша информационная база работает в распределённой инфраструктуре (например, сервер в Москве, а пользователи в Владивостоке), разница между датами может отличаться из-за временных зон. 1С учитывает эти настройки, но есть нюансы:
Пример проблемы: если на сервере (UTC+3) записана дата '2026-05-10 23:00:00', а пользователь в Хабаровске (UTC+10) открывает её в 6:00 следующего дня, то разница между "сейчас" и датой на сервере составит 31 час вместо ожидаемых 7.
Чтобы избежать ошибок:
- Настройте временную зону в параметрах информационной базы (
Администрирование → Настройки программы → Общие настройки). - Используйте
УниверсальноеВремя()для хранения дат в UTC:
ДатаUTC = УниверсальноеВремя(ТекущаяДата());
ДатаЛокальная = ЛокальноеВремя(ДатаUTC);
Для расчёта разницы с учётом временных зон:
Функция РазницаСУчетомВременныхЗон(Дата1, Дата2, ЧасовойПояс1, ЧасовойПояс2)
Дата1UTC = УниверсальноеВремя(Дата1, ЧасовойПояс1);
Дата2UTC = УниверсальноеВремя(Дата2, ЧасовойПояс2);
Возврат Дата2UTC - Дата1UTC;
КонецФункции;
Всегда храните даты в базе в формате UTC, а преобразование в локальное время выполняйте только при отображении пользователю. Это исключит ошибки при миграции серверов или изменении временных зон.
Пример вызова:
Разница = РазницаСУчетомВременныхЗон(
'2026-05-10 23:00:00',
'2026-05-11 06:00:00',
Новый ЧасовойПояс(3, 0), // UTC+3 (Москва)
Новый ЧасовойПояс(10, 0) // UTC+10 (Хабаровск)
);
// Вернёт 0.291666... (7 часов)
6. Практическое применение: примеры из реальных задач
Рассмотрим 3 типичные задачи, где требуется вычитание дат в 1С, и готовые решения для них.
Задача 1. Расчёт просрочки оплаты по счёту:
Процедура РассчитатьПросрочку(ДокументСчет)
ТекущаяДата = ТекущаяДата();
ДатаОплаты = ДокументСчет.ДатаОплаты;
Если ДатаОплаты = '0001-01-01' Тогда // Не оплачен
ДнейПросрочки = Цел(ТекущаяДата - ДокументСчет.Дата);
Если ДнейПросрочки > 0 Тогда
Сообщить(Формат("Просрочка: %1 дней", ДнейПросрочки));
КонецЕсли;
КонецЕсли;
КонецПроцедуры;
Задача 2. Определение возраста клиента (в годах):
Функция ВозрастВГодах(ДатаРождения)
Возврат Цел((ТекущаяДата() - ДатаРождения) / 365.25);
КонецФункции;
Задача 3. Расчёт времени выполнения заказа (с учётом рабочих дней):
Функция ВремяВыполненияЗаказа(ДатаСоздания, ДатаВыполнения)
Календарь = Календари.РабочийКалендарьОрганизации(ТекущаяОрганизация());
Возврат Календарь.РазницаВДнях(ДатаСоздания, ДатаВыполнения);
КонецФункции;
Для автоматизации подобных расчётов рекомендуем:
- 📂 Создавать
ОбщиеМодулис часто используемыми функциями (например,РазницаВРабочихДнях()). - 📊 Использовать
РегистрыСведенийдля хранения производственных календарей (это ускорит доступ к данным). - 🔄 Тестировать функции на крайних случаях (например, даты до 1900 года или переход через границу года).
FAQ: Частые вопросы по вычитанию дат в 1С
Как вычесть из даты 3 месяца, учитывая разное количество дней в месяцах?
Используйте функцию ДобавитьМесяц():
НоваяДата = ДобавитьМесяц(ТекущаяДата(), -3);
Эта функция корректно обрабатывает переходы между месяцами с разным количеством дней (например, 31 января → 30 апреля).
Почему при вычитании дат получается отрицательное число?
Отрицательный результат означает, что Дата1 позже Дата2. Например:
'2026-05-10' - '2026-05-15' // Вернёт -5
Чтобы избежать ошибок, всегда проверяйте порядок дат:
Если Дата1 > Дата2 Тогда
Разница = Дата1 - Дата2;
Иначе
Разница = Дата2 - Дата1;
КонецЕсли;
Как посчитать разницу между датами в минутах с точностью до секунды?
Умножьте разницу в днях на количество минут в дне (1440) и округлите:
РазницаВМинутах = Окр((Дата2 - Дата1) * 1440, 2);
Для секунд используйте коэффициент 86400.
Можно ли в 1С посчитать разницу между датами с учётом только рабочих часов (например, с 9:00 до 18:00)?
Да, но для этого потребуется написать кастомную функцию, которая:
- Разобьёт интервал на дни.
- Для каждого дня проверит, попадает ли время в рабочий интервал (например, 9:00–18:00).
- Просуммирует только рабочие часы.
Пример кода:
Код функции для рабочих часов
Функция РазницаВРабочихЧасах(ДатаНачала, ДатаОкончания, НачалоРабочегоДня = 9, КонецРабочегоДня = 18)
// Логика разбиения интервала на дни и учёта рабочих часов
// ...
КонецФункции;
Как в отчёте 1С отобразить разницу между датами в формате "X дней Y часов"?
Используйте комбинацию функций Цел() и Окр():
Дней = Цел(РазницаВДнях);
Часов = Окр((РазницаВДнях - Дней) * 24, 0);
Результат = Формат("Дней: %1, Часов: %2", Дней, Часов);