Как правильно добавить рабочие дни к дате в 1С:ЗУП

Программист 1С v8.3 (Управляемые формы) 1С:Зарплата и Управление Персоналом IT и автоматизация бизнеса
← На главную

При разработке отчетов или доработке логики в 1С:Зарплата и управление персоналом (ЗУП) часто возникает задача: прибавить к определенной дате заданное количество именно рабочих дней. В отличие от простых календарных дней, здесь необходимо учитывать праздники, выходные и возможные переносы. Давайте подробно разберем, как это реализовать наиболее эффективно, используя встроенные возможности Библиотеки стандартных подсистем (БСП) и механизмы запросов.

Способ 1: Использование стандартных функций БСП

Самый надежный и правильный способ в современных конфигурациях на базе 1С 8.3 — это использование общего модуля КалендарныеГрафики. В нем собраны все необходимые инструменты для работы с производственными календарями, включая справочник методов конфигурации Зарплата и кадры 3.1.

Рассмотрим основной метод ДатаПоКалендарю. Он позволяет вычислить дату, отстоящую от исходной на нужное количество рабочих дней. Проанализируем пример кода:


// Определяем календарь (обычно это основной производственный календарь РФ)
КалендарьСсылка = Справочники.ПроизводственныеКалендари.ПроизводственныйКалендарьПоУмолчанию();

// Исходная дата
ДатаНачала = ТекущаяДата(); 

// Добавляем 3 рабочих дня
КоличествоДней = 3;

НоваяДата = КалендарныеГрафики.ДатаПоКалендарю(КалендарьСсылка, ДатаНачала, КоличествоДней);

Важный нюанс: если вам нужно не просто добавить дни, а рассчитать срок окончания какой-либо задачи или действия, в актуальных версиях БСП рекомендуется использовать функцию ДатаЗавершенияСрока. Она работает более гибко: если передать в нее «0» рабочих дней, она вернет текущую дату (если это рабочий день) или ближайший следующий рабочий день.

Способ 2: Расчет даты через запрос к производственному календарю

Иногда задачу нужно решить внутри запроса (например, при разработке сложного отчета на СКД), где использование функций общего модуля невозможно или неэффективно. В этом случае мы обратимся напрямую к регистру сведений ДанныеПроизводственногоКалендаря, используя консоль запросов ЗУП с поддержкой обращения к методам программного интерфейса.

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


ВЫБРАТЬ ПЕРВЫЕ 1
    Календарь.Дата КАК ИскомаяДата
ИЗ
    РегистрСведений.ДанныеПроизводственногоКалендаря КАК Календарь
ГДЕ
    Календарь.ПроизводственныйКалендарь = &ПроизводственныйКалендарь
    И Календарь.Дата > &ДатаНачала
    И (Календарь.ВидДня = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Рабочий)
        ИЛИ Календарь.ВидДня = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Предпраздничный))
УПОРЯДОЧИТЬ ПО
    Календарь.Дата
АВТОУПОРЯДОЧИВАНИЕ

Чтобы получить именно третью дату, в реальном запросе нам придется использовать либо временные таблицы с нумерацией строк, либо механизм «ВЫБРАТЬ ПЕРВЫЕ 3» и последующую группировку (МАКСИМУМ), чтобы оставить только последнюю дату из этого набора.

Способ 3: Учет индивидуальных графиков работы сотрудников

В системе 1С:ЗУП важно различать «рабочие дни по стране» и «рабочие дни конкретного сотрудника». Если сотрудник работает по сменному графику (например, 2 через 2), то общероссийский производственный календарь ему не подходит. Рассмотрим, как решить задачу с учетом графика.

Для таких целей используется функция ГрафикиРаботы.ДатаПоГрафику (или аналогичные методы в модуле УчетРабочегоВремени). Вместо ссылки на календарь в параметры передается ссылка на график работы сотрудника из справочника ГрафикиРаботыСотрудников.

Проанализируем ситуацию: если нам нужно понять, когда сотрудник выйдет на смену через 3 своих рабочих дня, код будет выглядеть так:


ГрафикСотрудника = Объект.Сотрудник.ОсновнойГрфик; // Утрированный пример получения
КоличествоДней = 3;
ДатаНачала = ТекущаяДата();

Результат = КалендарныеГрафики.ДатаПоКалендарю(ГрафикСотрудника, ДатаНачала, КоличествоДней);

Способ 4: Написание собственной функции проверки рабочего дня

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


Функция ДобавитьРабочиеДни(ДатаНачала, КоличествоДней) Экспорт
    ТекДата = ДатаНачала;
    ДобавленоДней = 0;
    
    Пока ДобавленоДней < КоличествоДней Цикл
        ТекДата = ТекДата + 86400; // Добавляем 1 день в секундах
        
        // Проверяем через регистр сведений
        СведенияНаДень = РегистрыСведений.ДанныеПроизводственногоКалендаря.Получить(Новый Структура("Дата", ТекДата));
        
        Если СведенияНаДень.ВидДня = Перечисления.ВидыДнейПроизводственногоКалендаря.Рабочий 
           ИЛИ СведенияНаДень.ВидДня = Перечисления.ВидыДнейПроизводственногоКалендаря.Предпраздничный Тогда
            ДобавленоДней = ДобавленоДней + 1;
        КонецЕсли;
    КонецЦикла;
    
    Возврат ТекДата;
КонецФункции

Рекомендации по стабильности кода

Разберем несколько важных моментов, которые часто упускают программисты при работе с датами:

  1. Проверка заполнения календаря: В конце календарного года функции могут возвращать пустую дату или вызывать ошибку, если производственный календарь на следующий год еще не загружен в базу. Всегда используйте КалендарныеГрафики.ПроверитьЗаполнениеГрафика() перед расчетами.
  2. Отрицательные значения: Помните, что функция ДатаПоКалендарю умеет работать и в обратную сторону. Если передать -3, вы получите дату, которая была 3 рабочих дня назад.
  3. Часовые пояса: При работе с датами типа Дата в 1С всегда следите за тем, чтобы время было обнулено (начало дня), иначе сравнения в запросах или получение среза последних могут отработать некорректно.

Таким образом, для большинства задач в ЗУП 3.1 оптимальным решением будет использование общего модуля КалендарныеГрафики. Это гарантирует корректность расчетов с учетом всех законодательных переносов выходных дней, утвержденных правительством.

← На главную