Расчет количества дней между двумя датами — одна из самых частых задач в 1С. Она возникает при работе с графиками, сроками оплаты, отчетными периодами, отпусками и многими другими бизнес-процессами. Казалось бы, что может быть проще? Но на практике даже опытные разработчики сталкиваются с нюансами: нужно ли учитывать выходные, как обрабатывать неполные дни, что делать с временными зонами или как избежать ошибок при переходе на зимнее/летнее время.
В этой статье мы разберем 5 рабочих способов посчитать дни между датами в 1С:Предприятие 8.3/8.2, от элементарных встроенных функций до сложных алгоритмов с учетом производственного календаря. Каждый метод проиллюстрирован реальными примерами кода, которые вы сможете сразу использовать в своих конфигурациях — будь то УТ 11, БП 3.0, ЗУП 3.1 или ERP 2.5.
Особое внимание уделим типичным ошибкам, которые приводят к некорректным расчетам. Например, почему функция ДеньГода может дать неверный результат при работе с датами разных лет, или как правильно округлить дробные дни при расчете рабочего времени. Также вы узнаете, как оптимизировать запросы к базе данных, если нужно посчитать дни для тысяч записей — это критично для производительности в больших информационных базах.
Если вы новичок в 1С, начните с первых двух способов — они не требуют глубоких знаний в программировании. Опытным разработчикам будут полезны разделы про Запросы и Расширения стандартных механизмов, где мы покажем неочевидные приемы для работы с датами в типовой функциональности.
1. Самый простой способ: функция РазностьДат
Начнем с базового метода, который подходит для 90% задач. В 1С есть встроенная функция РазностьДат, которая возвращает разницу между двумя датами в заданных единицах измерения. Для подсчета дней используем параметр "День".
Синтаксис функции:
РазностьДат(КонечнаяДата, НачальнаяДата,"День")
Пример 1. Рассчитаем количество дней между 1 января и 10 января 2026 года:
КоличествоДней = РазностьДат('20260110','20260101',"День");
// Результат: 9
Пример 2. Если нужно посчитать дни между текущей датой и какой-либо прошлой датой:
ТекущаяДата = ТекущаяДата;
ПрошлаяДата ='20231201';
КоличествоДней = РазностьДат(ТекущаяДата, ПрошлаяДата,"День");
✅ Плюсы метода:
- 🔹 Простота — одна строка кода
- 🔹 Работает во всех конфигурациях 1С без дополнительных настроек
- 🔹 Учитывает високосные годы автоматически
❌ Ограничения:
- 🚫 Не учитывает выходные и праздничные дни
- 🚫 Не работает с временными метками (только даты без времени)
- 🚫 Не подходит для расчета рабочего времени
Если вам нужно посчитать дни между датами с учетом времени (например, 10:00 01.01.2026 и 14:30 02.01.2026), используйте функцию РазностьДат с параметром "Секунда", а затем конвертируйте результат в дни, разделив на 86400 (количество секунд в сутках).
2. Альтернативный метод: вычитание дат
В 1С даты можно вычитать друг из друга напрямую — результат будет в днях. Этот способ еще проще, чем РазностьДат, но имеет свои нюансы.
Пример:
Дата1 ='20260315';
Дата2 ='20260320';
КоличествоДней = Дата2 - Дата1;
// Результат: 5
🔍 Важная особенность: если вычитать даты в обратном порядке (более раннюю из поздней), результат будет отрицательным. Это можно использовать для проверки корректности введенных дат:
Если ДатаОкончания < ДатаНачала Тогда
Сообщить("Дата окончания раньше даты начала!");
КонецЕсли;
⚠️ Внимание: при вычитании дат с временем (тип ДатаВремя) результат будет в долях дня. Например, разница между '20260101 12:00:00' и '20260101 00:00:00' составит 0.5 (полдня).
📌 Когда использовать этот метод:
- 📅 Для быстрых расчетов в отчетах или обработках
- 🔄 Когда нужно проверить логическую последовательность дат
- ⚡ Для операций с большими массивами данных (вычитание работает быстрее, чем
РазностьДат)
3. Расчет дней с учетом рабочего календаря
Если вам нужно посчитать только рабочие дни (исключая выходные и праздники), стандартные функции 1С не подойдут. Здесь потребуется использовать ПроизводственныйКалендарь — объект, который есть в большинстве типовых конфигураций (ЗУП, ERP, БП).
Пример кода для расчета рабочих дней:
ПроизвКалендарь = Календари.ПроизводственныйКалендарь;
ДатаНачала ='20260101';
ДатаОкончания ='20260131';
// Получаем количество рабочих дней в периоде
КоличествоРабочихДней = ПроизвКалендарь.КоличествоРабочихДней(ДатаНачала, ДатаОкончания);
📊 Сравнение методов:
| Метод | Учитывает выходные | Учитывает праздники | Требует доработок |
|---|---|---|---|
РазностьДат |
❌ Нет | ❌ Нет | ❌ Нет |
| Вычитание дат | ❌ Нет | ❌ Нет | ❌ Нет |
ПроизводственныйКалендарь |
✅ Да | ✅ Да | ⚠️ Только в типовых конфигурациях |
| Собственная функция | ✅ Да | ✅ Да | ✅ Требует разработки |
⚠️ Внимание: в нетиповых конфигурациях объекта ПроизводственныйКалендарь может не быть. В этом случае придется создавать свой календарь с учетом выходных или интегрироваться с внешними сервисами (например, через HTTP-запросы к государственным календарям праздников).
🔹 Как быть, если нет ПроизводственногоКалендаря?
- 📌 Создать справочник с праздничными датами и проверять попадание в него
- 📌 Использовать внешнюю обработку с готовым календарем
- 📌 Написать функцию, которая будет пропускать субботу и воскресенье
Пример функции для расчета рабочих дней без ПроизводственногоКалендаря
Функция КоличествоРабочихДней(ДатаНачала, ДатаОкончания)
ТекущаяДата = ДатаНачала;
Счетчик = 0;
Пока ТекущаяДата <= ДатаОкончания Цикл
ДеньНедели = ДеньНедели(ТекущаяДата);
Если НЕ (ДеньНедели = 6 ИЛИ ДеньНедели = 7) Тогда // Пропускаем субботу и воскресенье
Счетчик = Счетчик + 1;
КонецЕсли;
ТекущаяДата = ТекущаяДата + 86400; // +1 день
КонецЦикла;
Возврат Счетчик;
КонецФункции
4. Расчет дней через запросы к базе данных
Если вам нужно посчитать дни между датами для большого количества записей (например, для всех документов в базе), оптимально использовать запросы 1С. Это значительно ускорит обработку по сравнению с пообъектным перебором.
Пример 1. Простой запрос для расчета разницы в днях между датой документа и текущей датой:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Документ.Ссылка КАК Ссылка,
| РАЗНОСТЬДАТ(ТЕКУЩАЯДАТА, Документ.Дата, ДЕНЬ) КАК ДнейПрошло
|ИЗ
| Документ.ЗаказПокупателя КАК Документ
|ГДЕ
| Документ.Дата > ДАТАВРЕМЯ(2026, 1, 1)";
Пример 2. Запрос с группировкой по периодам (например, посчитать количество дней между датой создания и датой оплаты для каждого заказа):
Запрос.Текст =
"ВЫБРАТЬ
| Заказ.Ссылка КАК Заказ,
| МАКСИМУМ(ВЫБОР
| КОГДА Заказ.ДатаОплаты ЕСТЬ NULL
| ТОГДА 0
| ИНАЧЕ РАЗНОСТЬДАТ(Заказ.ДатаОплаты, Заказ.Дата, ДЕНЬ)
| КОНЕЦ) КАК ДнейДоОплаты
|ИЗ
| Документ.ЗаказПокупателя КАК Заказ
|СГРУППИРОВАТЬ ПО
| Заказ.Ссылка";
💡 Советы по оптимизации запросов:
- 🔧 Используйте
ИНДЕКСИРОВАТЬ ПОдля полей с датами, если запрос работает медленно - 🔧 Избегайте вычислений в
ГДЕ— переносите их вВЫБРАТЬ - 🔧 Для больших баз разбейте запрос на части с помощью
ОБЪЕДИНИТЬ
⚠️ Внимание: в запросах функция РАЗНОСТЬДАТ работает иначе, чем встроенная функция РазностьДат! Например, РАЗНОСТЬДАТ('20260110','20260101', ДЕНЬ) вернет 9, а РазностьДат('20260110','20260101',"День") — тоже 9. Но если поменять даты местами, результат будет разным: запрос вернет отрицательное число, а функция — положительное.
🔹 Убедитесь, что поля с датами проиндексированы
🔹 Проверьте, что в выборке нет NULL-значений для дат
🔹 Ограничьте период выборки (например, за последний год)
🔹 Протестируйте запрос на небольшом объеме данных-->
5. Учет временных зон и летнего/зимнего времени
Если ваша база 1С работает с клиентами или филиалами в разных часовых поясах, при расчете дней между датами могут возникать ошибки. Например, разница между '20260331 23:00:00' и '20260401 01:00:00' в Москве и Екатеринбурге будет разной из-за перехода на летнее время.
Как решить проблему:
- 🌍 Приведите все даты к одному часовому поясу с помощью функции
ЧасовойПояс:
ДатуМск = ЧасовойПояс(ДатуСЧасовымПоясом,"Europe/Moscow");
- 🕒 Используйте тип
ДатаВремявместоДата, если важно время:
РазницаВоВремени = Дата2 - Дата1; // Результат в днях (может быть дробным)
РазницаВДнях = Цел(РазницаВоВремени); // Округляем до целых дней
📌 Таблица часовых поясов в 1С:
| Часовый пояс | Идентификатор в 1С | Смещение от UTC |
|---|---|---|
| Москва | "Europe/Moscow" |
UTC+3 |
| Екатеринбург | "Asia/Yekaterinburg" |
UTC+5 |
| Новосибирск | "Asia/Novosibirsk" |
UTC+7 |
| Владивосток | "Asia/Vladivostok" |
UTC+10 |
⚠️ Внимание: при работе с временными зонами учитывайте, что переход на летнее/зимнее время в разных странах происходит в разные даты. Например, в России с 2014 года переход отменен, а в Европе он все еще действует. Это может привести к расхождению в 1 час при расчетах.
🔹 Как избежать ошибок:
- 🕐 Храните все даты в базе в
UTC, а преобразовывайте в локальное время только при отображении - 🕐 Используйте функцию
ЛокальнаяДатадля приведения к текущему поясу пользователя - 🕐 Проверяйте настройки часовых поясов в
Администрирование → Настройки программы
При расчете дней между датами с временем всегда приводите их к одному часовому поясу или используйте UTC. Это избавит от ошибок при переходе на летнее/зимнее время и работе с распределенными базами.
6. Сложные случаи: неполные дни, округление, календарные особенности
Иногда требуется не просто посчитать дни, а решить более сложные задачи:
- 📅 Неполные дни: например, если событие началось в 14:00 01.01.2026 и закончилось в 10:00 02.01.2026, нужно ли считать это как 1 день или 2?
- 🔄 Округление: если разница составила 1.6 дня, округлять до 1 или 2?
- 🎭 Календарные особенности: например, в исламском календаре длительность месяцев разная.
Пример 1. Округление дней в большую сторону (например, для расчета пеней):
Разница = ДатаОкончания - ДатаНачала;
КоличествоДней = Окр(Разница, 0); // Округление до целых
// Или
КоличествоДней = Цел(Разница) +?(Разница - Цел(Разница) > 0, 1, 0); // Округление вверх
Пример 2. Учет только полных дней (игнорируем время):
ДатаНачалаБезВремени = НачалоДня(ДатаНачала);
ДатаОкончанияБезВремени = НачалоДня(ДатаОкончания) + 86400; // +1 день для включения конечной даты
КоличествоПолныхДней = ДатаОкончанияБезВремени - ДатаНачалаБезВремени;
Критичный нюанс: при расчете дней для юридически значимых документов (например, сроков оплаты по договору) всегда уточняйте в нормативных актах, как именно считаются дни: календарные или рабочие, включаются ли праздники, как округляются неполные сутки. Например, по ст. 193 ГК РФ последний день срока истекает в 24:00, а если это выходной — переносится на следующий рабочий день.
🔹 Чек-лист для сложных расчетов:
🔹 Уточните, нужно ли учитывать время (или только даты)
🔹 Определите правила округления (вверх, вниз, к ближайшему)
🔹 Проверьте, влияют ли на расчет праздники/выходные
🔹 Убедитесь, что часовой пояс учтен корректно-->
7. Типичные ошибки и как их избежать
Даже опытные разработчики 1С иногда допускают ошибки при работе с датами. Вот самые распространенные:
🔴 Ошибка 1. Использование функции ДеньГода для расчета разницы:
// НЕПРАВИЛЬНО!
День1 = ДеньГода(Дата1);
День2 = ДеньГода(Дата2);
Разница = День2 - День1; // Ошибка, если даты в разных годах!
✅ Решение: используйте РазностьДат или вычитание дат.
🔴 Ошибка 2. Игнорирование NULL-значений:
// НЕПРАВИЛЬНО - вылетит ошибка, если ДатаОкончания не заполнена
Разница = ДатаОкончания - ДатаНачала;
✅ Решение: всегда проверяйте заполненность дат:
Если ДатаОкончания ='00010101' ИЛИ ДатаНачала ='00010101' Тогда
Возврат 0;
КонецЕсли;
🔴 Ошибка 3. Неучет переходов через полночь при работе с ДатаВремя:
// НЕПРАВИЛЬНО - может дать неверный результат при переходе через 00:00
РазницаВДнях = Цел((ДатаОкончания - ДатаНачала) / 86400);
✅ Решение: используйте НачалоДня для приведения к датам без времени.
📌 Как тестировать код с датами:
- 🧪 Проверяйте граничные случаи: переход через полночь, конец месяца, високосный год
- 🧪 Тестируйте с пустыми датами (
'00010101') - 🧪 Сравнивайте результаты с ручным подсчетом в календаре
Всегда тестируйте расчеты дней на датах, попадающих на переходы между месяцами, годами и часовыми поясами. Особенно критично это для финансовых расчетов, где ошибка в один день может привести к неправильному начислению пеней или штрафов.
FAQ: Ответы на частые вопросы
Как посчитать количество полных недель между датами?
Используйте функцию РазностьДат с параметром "Неделя":
ПолныхНедель = РазностьДат(Дата2, Дата1,"Неделя");
Если нужно учитывать только полные недели (7 дней), используйте:
ПолныхНедель = Цел(РазностьДат(Дата2, Дата1,"День") / 7);
Можно ли посчитать дни между датами в отчете без программирования?
Да, в большинстве типовых конфигураций (УТ, БП, ЗУП) можно добавить вычисляемое поле в отчет:
- Откройте настройки отчета
- Добавьте новое поле типа"Выражение"
- Введите формулу:
РАЗНОСТЬДАТ(ДатаОкончания, ДатаНачала, ДЕНЬ)
Если такого поля нет, обратитесь к администратору 1С для доработки отчета.
Как посчитать дни между датами в управленческом учете (ERP 2)?
В ERP 2.5 для расчета дней между датами документов можно:
- Использовать стандартные отчеты с группировкой по периодам
- Создать внешнюю обработку с нужной логикой
- Добавить вычисляемое поле в динамический список через
УправлениеДинамическимСписком
Для сложных расчетов (например, с учетом рабочих дней) лучше написать собственную функцию или использовать ПроизводственныйКалендарь.
Почему РазностьДат возвращает неверное количество дней для исторических дат?
Это связано с тем, что в 1С даты до 1900 года обрабатываются некорректно из-за особенностей григорианского календаря. Для исторических расчетов:
- Используйте внешние библиотеки для работы с датами
- Преобразуйте даты влианский формат перед расчетом
- Ограничьте период расчетов датами после 1900 года
Как посчитать дни между датами в мобильном приложении 1С?
В мобильной платформе 1С:Предприятие доступны те же функции:
// В мобильном клиенте
КоличествоДней = РазностьДат(Дата2, Дата1,"День");
Ограничения:
- Нет доступа к
ПроизводственномуКалендарю(придется реализовывать свой) - Запросы работают медленнее, чем на сервере
Рекомендация: переносите сложные расчеты на сервер через ВыполнитьНаСервере.