Как рассчитать общую продолжительность перерывов внутри наряда в 1С

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

В процессе разработки систем автоматизации производства или учета трудозатрат часто возникает задача определения «чистого» рабочего времени. Например, когда наряд на сдельную работу выполняется в течение дня, но внутри этого периода существуют фиксированные технологические перерывы или обед. Нам необходимо корректно вычесть время отдыха из общей длительности работ, чтобы получить точные данные для начисления зарплаты или анализа производительности.

В этой статье мы подробно разберем, как реализовать алгоритм расчета перерывов, рассмотрим различные подходы от простых циклов до профессиональных методов платформы 1С и обсудим нюансы работы с типами данных Дата и Число.

Метод 1. Перебор интервалов с логической проверкой

Рассмотрим самый очевидный способ, который часто первым приходит в голову разработчику. Суть заключается в том, что мы имеем таблицу с фиксированными перерывами (например, в виде ТаблицаЗначений или массива структур) и проверяем каждый перерыв на предмет его вхождения в интервал работы по наряду.

Для реализации этого метода нам понадобятся две переменные: НачалоНаряда и КонецНаряда. Предположим, что перерывы также заданы временем начала и окончания. Проанализируем пример кода, который реализует базовую логику:


// Предположим, у нас есть ТаблицаПерерывов с колонками ВремяНачала, ВремяОкончания, Продолжительность
ЧистоеРабочееВремя = КонецНаряда - НачалоНаряда; // Изначально в секундах

Для Каждого СтрокаПерерывов Из ТаблицаПерерывов Цикл
    // Проверяем, попадает ли перерыв полностью внутрь наряда
    Если СтрокаПерерывов.ВремяНачала >= НачалоНаряда И СтрокаПерерывов.ВремяОкончания <= КонецНаряда Тогда
        ЧистоеРабочееВремя = ЧистоеРабочееВремя - (СтрокаПерерывов.ВремяОкончания - СтрокаПерерывов.ВремяНачала);
    КонецЕсли;
КонецЦикла;

Однако, как справедливо замечено в обсуждении, этот код не учитывает ситуации, когда наряд начинается или заканчивается прямо во время перерыва. Чтобы сделать алгоритм надежным, нам придется добавить множество условий ИначеЕсли, проверяющих частичное пересечение. Это усложняет код и повышает риск ошибок.

Метод 2. Универсальная формула пересечения интервалов

Разберем более изящный математический способ. Чтобы вычислить длительность пересечения двух любых временных отрезков (Интервал А и Интервал Б), не нужно писать сложные ветвления. Существует универсальная формула: ДлительностьПересечения = Максимум(0, Минимум(КонецА, КонецБ) - Максимум(НачалоА, НачалоБ)).

Этот подход автоматически обрабатывает все случаи:

  1. Перерыв полностью внутри наряда.
  2. Наряд начался во время перерыва.
  3. Наряд закончился во время перерыва.
  4. Перерыв вообще не пересекается с нарядом (результат будет 0).

Посмотрим на пример функции, реализующей этот подход:


Функция РассчитатьВремяПерерывов(НачалоНаряда, КонецНаряда, ТаблицаПерерывов)
    ОбщееВремяПерерывов = 0;
    
    Для Каждого ТекущийПерерыв Из ТаблицаПерерывов Цикл
        НачалоПересечения = Макс(НачалоНаряда, ТекущийПерерыв.ВремяНачала);
        КонецПересечения = Мин(КонецНаряда, ТекущийПерерыв.ВремяОкончания);
        
        Длительность = КонецПересечения - НачалоПересечения;
        
        Если Длительность > 0 Тогда
            ОбщееВремяПерерывов = ОбщееВремяПерерывов + Длительность;
        КонецЕсли;
    КонецЦикла;
    
    Возврат ОбщееВремяПерерывов;
КонецФункции

Важный момент: В 1С при вычитании одной даты из другой результат всегда получается в секундах. Это удобно для расчетов. Если вам нужно получить результат в минутах, разделите итоговое значение на 60.

Метод 3. Использование графиков работы и встроенных функций платформы

В типовых конфигурациях (таких как ЗУП, ERP или КА) существуют механизмы, которые уже умеют работать с графиками. Если ваши перерывы жестко регламентированы, их можно заложить в График работы. В платформе 1С предусмотрены программные интерфейсы для работы с такими графиками.

Выясним, как это работает. Например, можно использовать методы общего модуля КалендарныеГрафики. Функция ОтработанноеВремяВСекундах() (название может варьироваться в зависимости от версии БСП) принимает на вход две даты и ссылку на график. Она автоматически вычитает все нерабочие периоды, праздники и те самые перерывы, которые мы пытаемся посчитать вручную.

Этот метод считается наиболее профессиональным по нескольким причинам:

Оптимизация хранения данных через Регистр сведений

Проанализируем ситуацию, когда перерывов много или они меняются со временем. Жестко прописывать время перерывов в программном коде — плохая практика («хардкод»). Оптимальным решением будет создание Регистра сведений (например, РасписаниеПерерывов).

В таком регистре стоит хранить:

Это позволит использовать Запросы для массового расчета нарядов. Если у вас тысячи документов за месяц, расчет в цикле может замедлить систему. В запросе же можно применить логику ВЫБОР КОГДА... для реализации формулы пересечения интервалов, что позволит получить данные по всем нарядам одним обращением к базе данных.

Проблема перехода через полночь

Посмотрим на ситуацию, которую часто упускают из виду: работа в ночную смену. Если наряд начался в 22:00, а закончился в 06:00 следующего дня, обычное сравнение времени может дать сбой.

Чтобы избежать ошибок при переходе через границу суток, придерживайтесь следующих правил:

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

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

← На главную