Разберем частую задачу, с которой сталкиваются разработчики — подсчет количества рабочих дней между двумя заданными датами. При решении этой задачи часто возникает соблазн «изобрести велосипед», написав собственный алгоритм с перебором дней в цикле и проверкой каждого на принадлежность к выходным. Однако в современных типовых конфигурациях (таких как «Бухгалтерия предприятия 3.0», «Зарплата и управление персоналом 3» и других), построенных на базе Библиотеки стандартных подсистем (БСП), уже есть готовые инструменты. Рассмотрим их подробнее.
Для работы с производственными календарями в типовых конфигурациях предусмотрена специальная подсистема БСП. Проанализируем общий модуль КалендарныеГрафики, в котором содержится нужный нам алгоритм.
Чтобы получить разность дат с учетом выходных и праздников, используем готовую функцию РазностьДатПоКалендарю. Посмотрим на пример вызова данной функции:
// Получаем ссылку на основной производственный календарь (например, РФ)
ГрафикРаботы = Справочники.ПроизводственныеКалендари.НайтиПоНаименованию("Российская Федерация");
// Вычисляем количество рабочих дней
КоличествоДней = КалендарныеГрафики.РазностьДатПоКалендарю(ГрафикРаботы, ДатаНачала, ДатаОкончания, Ложь);
Разберем по шагам параметры, которые принимает эта функция:
Истина, то при отсутствии данных в календаре на указанный год программа выдаст ошибку. Если передать Ложь, функция просто вернет Неопределено, что позволит обработать эту ситуацию программно без прерывания работы кода.Важное замечание: Если вы поддерживаете старые конфигурации, вы можете встретить метод ПолучитьРазностьДатПоКалендарю. В актуальных версиях БСП методы с приставкой «Получить» признаны устаревшими и оставлены только для обратной совместимости. Настоятельно рекомендуем использовать именно РазностьДатПоКалендарю.
Методы общих модулей нельзя использовать напрямую внутри текстов запросов. Выясним, как быть, если количество рабочих дней между датами нужно вычислить динамически — например, для вывода в отчете на Системе Компоновки Данных (СКД) или в колонке динамического списка.
В этом случае задача решается через язык запросов с обращением к регистру сведений ДанныеПроизводственногоКалендаря. Проанализируем логику построения такого запроса:
ДанныеПроизводственногоКалендаря.Дата из регистра должно находиться между нашей ДатаНачала и ДатаОкончания.ВидДня. Нас интересуют только значения перечисления, соответствующие рабочему времени: Рабочий или Предпраздничный.КОЛИЧЕСТВО(ДанныеПроизводственногоКалендаря.Дата), которая подсчитает итоговое число подходящих записей.Посмотрим на пример подобного запроса:
ВЫБРАТЬ
Документы.Ссылка КАК Документ,
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Календарь.Дата) КАК РабочихДней
ИЗ
Документ.ЗаказКлиента КАК Документы
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ДанныеПроизводственногоКалендаря КАК Календарь
ПО Календарь.Дата МЕЖДУ Документы.Дата И Документы.ДатаОтгрузки
И (Календарь.ВидДня = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Рабочий)
ИЛИ Календарь.ВидДня = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Предпраздничный))
И Календарь.ПроизводственныйКалендарь = &ПроизводственныйКалендарь
СГРУППИРОВАТЬ ПО
Документы.Ссылка
Помимо расчета разности дат, в общем модуле КалендарныеГрафики есть и другие полезные методы. Рассмотрим некоторые из них:
ДатыБлижайшихРабочихДней — отличный инструмент для ситуаций, когда нужно определить срок выполнения задачи. Если плановая дата попадает на выходной, эта функция поможет найти ближайший рабочий день (со сдвигом вперед или назад).Используя стандартные механизмы БСП и данные производственных календарей, мы можем легко и безошибочно рассчитывать рабочие дни, не усложняя код собственными нестандартными алгоритмами.