Как рассчитать разницу между двумя датами в минутах с учетом рабочих часов?

Программист 1С v8.3 (Обычные формы) Управленческий учет Сфера услуг, туризм и социальный сектор
← На главную

В процессе разработки отчетов в 1С, особенно в таких конфигурациях, как Альфа-Авто, часто возникает задача подсчета чистого рабочего времени между двумя событиями. Например, нам нужно узнать, сколько минут прошло с момента создания заказ-наряда до его закрытия, учитывая, что мастера работают только с 09:00 до 21:00. Если документ был создан ночью, отсчет должен начаться только с начала рабочей смены. Разберем несколько способов решения этой задачи: от математических формул до сложных запросов.

Метод 1: Математический расчет разницы в минутах

Если нам необходимо выполнить расчет в коде на языке 1С, мы можем воспользоваться формулой, которая разбивает интервал на три части: полные рабочие сутки между датами, остаток времени в первый день и прошедшее время в последний день. Рассмотрим логику, которую предложили участники обсуждения. Предположим, рабочая смена длится 12 часов (с 9 до 21), что составляет 720 минут.

Проанализируем алгоритм расчета:

  1. Вычисляем количество полных суток между датами (исключая день начала и день окончания).
  2. Умножаем это количество на общую длительность смены (720 минут).
  3. Рассчитываем рабочие минуты в день начала (от времени старта до 21:00, но не ранее 09:00).
  4. Рассчитываем рабочие минуты в день окончания (от 09:00 до времени закрытия, но не позднее 21:00).

Посмотрим на пример реализации такой функции:


ДельтаМинутЦелыхСуток = Макс(0, Окр((НачалоДня(ДатаКон) - НачалоДня(ДатаНач))/(24*60*60),0)-1) * ((21-9)*60);
МинутНачДатыДоКонСуток = Макс(0, (КонецДня(ДатаНач) - (24-21)*60*60) - Макс(ДатаНач, НачалоДня(ДатаНач) + 9*60*60)) / 60;
МинутКонДатыОтНачСуток = Макс(0, Мин(ДатаКон, НачалоДня(ДатаКон) + 21*60*60) - (НачалоДня(ДатаКон) + 9*60*60)) / 60;
ДельтаРабМинут = ДельтаМинутЦелыхСуток + МинутНачДатыДоКонСуток + МинутКонДатыОтНачСуток;

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

Метод 2: Реализация через запрос 1С

Реализация подобной логики в запросе гораздо сложнее, так как в языке запросов 1С отсутствуют гибкие математические функции, доступные во встроенном языке. Однако это возможно с использованием конструкции ВЫБОР и функции РАЗНОСТЬДАТ. Основная сложность заключается в «обрезании» времени начала и окончания, если они выпадают на нерабочие часы.

Рассмотрим структуру запроса, который позволяет вычислить разницу:


ВЫБРАТЬ
    РАЗНОСТЬДАТ(&НачалоРВ, &КонецРВ, МИНУТА) * 
    ВЫБОР
        КОГДА РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачала, ДЕНЬ, 1), ДЕНЬ), НАЧАЛОПЕРИОДА(&ДатаОкончания, ДЕНЬ), ДЕНЬ) > 0
            ТОГДА РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачала, ДЕНЬ, 1), ДЕНЬ), НАЧАЛОПЕРИОДА(&ДатаОкончания, ДЕНЬ), ДЕНЬ)
        ИНАЧЕ 0
    КОНЕЦ + 
    ВЫБОР
        КОГДА РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(&ДатаНачала, ДЕНЬ), &ДатаНачала, МИНУТА) < РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(&НачалоРВ, ДЕНЬ), &НачалоРВ, МИНУТА)
            ТОГДА РАЗНОСТЬДАТ(&НачалоРВ, &КонецРВ, МИНУТА)
        КОГДА РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(&ДатаНачала, ДЕНЬ), &ДатаНачала, МИНУТА) < РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(&КонецРВ, ДЕНЬ), &КонецРВ, МИНУТА)
            ТОГДА РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(&КонецРВ, ДЕНЬ), &КонецРВ, МИНУТА) - РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(&ДатаНачала, ДЕНЬ), &ДатаНачала, МИНУТА)
        ИНАЧЕ 0
    КОНЕЦ КАК Минуты

В этом подходе &НачалоРВ и &КонецРВ — это границы рабочего времени (например, 09:00 и 21:00 одного дня). Выясним причину такой сложности: запрос должен отдельно обрабатывать ситуацию, когда начало и конец периода приходятся на один и тот же день, и ситуацию, когда они разделены несколькими сутками. Для точного отчета рекомендуется предварительно подготавливать данные (нормализовать даты) перед передачей их в запрос.

Метод 3: Использование механизмов «Альфа-Авто 5»

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

Алгоритм работы с регистром в запросе будет следующим: мы выбираем записи из регистра ГрафикРаботыРесурсов, которые попадают в период между ДатаСоздания и ДатаЗакрытия. Для каждой записи определяем фактическое начало (максимум из начала смены и начала документа) и фактический конец (минимум из конца смены и конца документа). После чего применяем функцию РАЗНОСТЬДАТ(..., МИНУТА) и суммируем результат по всему документу.

Дополнительные рекомендации по нормализации дат

Если вы решили использовать программный расчет или простые формулы в запросе, важно выполнить процедуру нормализации. Выясним, что это такое. Если документ создан в 05:00 утра, а работа начинается в 09:00, то для всех расчетов ДатаНачала должна быть приравнена к 09:00 того же дня. Если же документ закрыт в 23:00, время окончания для расчета должно стать 21:00.

Посмотрим, как это сделать во встроенном языке:


Если Час(ДатаСоздания) < 9 Тогда
    РабочаяДатаНачала = НачалоДня(ДатаСоздания) + 9 * 3600;
ИначеЕсли Час(ДатаСоздания) >= 21 Тогда
    РабочаяДатаНачала = НачалоДня(ДатаСоздания + 86400) + 9 * 3600;
Иначе
    РабочаяДатаНачала = ДатаСоздания;
КонецЕсли;

Такая предварительная обработка данных значительно упростит последующие формулы в запросе и сделает ваш отчет более надежным и понятным для пользователя.

← На главную