Задачи, связанные с расчетом времени пребывания сотрудника на территории или длительностью выполнения определенных операций, встречаются повсеместно. В системе 1С:Предприятие 8 работа с датами имеет свои особенности, которые могут запутать начинающего разработчика, особенно если в метаданных выбран состав даты Время. В этой статье мы подробно разберем, как правильно вычислить разницу во времени, как обработать переход через полночь и как красиво представить результат пользователю.
Для начала проанализируем ситуацию: у нас есть два реквизита типа Дата с составом Время. Важно понимать, что в 1С тип Дата всегда содержит и календарный день, и время (часы, минуты, секунды). Если мы указываем в свойствах «Состав даты: Время», платформа просто скрывает дату в интерфейсе, но внутри объекта она остается пустой — '00010101' (1 января 0001 года).
Рассмотрим основной принцип: при вычитании одной даты из другой в 1С результат всегда получается в секундах. Это числовой показатель, который является базой для всех дальнейших расчетов.
// Пример базового расчета
РазницаВСекундах = ВремяВыхода - ВремяВхода;
Если мы используем только время (без учета даты), то неизбежно столкнемся с проблемой, когда вход был осуществлен вечером одного дня (например, в 23:00), а выход — ночью следующего дня (в 02:00). Поскольку дата у обоих значений одинаковая (пустая), обычное вычитание даст отрицательный результат, что некорректно для расчета длительности.
Выясним, как это решить. Мы можем использовать условие: если время окончания меньше времени начала, значит, произошло пересечение суток, и нам нужно добавить к результату количество секунд в сутках (86 400 секунд).
Разберем пример кода, который учитывает этот нюанс:
РазницаВСекундах = ВремяВыхода - ВремяВхода;
Если РазницаВСекундах < 0 Тогда
// Если вышли позже, чем зашли (в рамках пустой даты),
// прибавляем 24 часа в секундах
РазницаВСекундах = РазницаВСекундах + 86400;
КонецЕсли;
Полученное число секунд нужно перевести в человекочитаемый строковый вид. Рассмотрим несколько способов форматирования.
Способ 1: Использование математических вычислений
Этот метод наиболее универсален, так как позволяет выводить любое количество часов (даже если их больше 24).
ВсегоЧасов = Цел(РазницаВСекундах / 3600);
Минуты = Цел((РазницаВСекундах - ВсегоЧасов * 3600) / 60);
// Форматируем строку для вывода вида "03:30"
РезультатСтрокой = Формат(ВсегоЧасов, "ЧЦ=2; ЧВН=") + ":" + Формат(Минуты, "ЧЦ=2; ЧВН=");
Способ 2: Использование функции Формат() к пустой дате
Если мы точно знаем, что разница времени не превышает 24 часа, можно применить изящный прием: прибавить полученные секунды к «нулевой» дате и применить стандартное форматирование времени.
// Прибавляем секунды к пустой дате и форматируем
Результат = Формат('00010101' + РазницаВСекундах, "ДЛФ=T");
Если расчет необходимо произвести на уровне базы данных (в запросе), используется функция РАЗНОСТЬДАТ. Однако она возвращает целое число в указанных единицах измерения (секунды, минуты, часы). Посмотрим, как вычислить точную разницу в секундах:
ВЫБРАТЬ
РАЗНОСТЬДАТ(Т.ВремяВхода, Т.ВремяВыхода, СЕКУНДА) КАК СекундыВсего
ИЗ
РегистрСведений.ВремяПрибытия КАК Т
Проанализируем ситуацию: в запросе также нужно учитывать переход через полночь. Это можно сделать через конструкцию ВЫБОР:
ВЫБРАТЬ
ВЫБОР
КОГДА Т.ВремяВыхода < Т.ВремяВхода
ТОГДА РАЗНОСТЬДАТ(Т.ВремяВхода, Т.ВремяВыхода, СЕКУНДА) + 86400
ИНАЧЕ РАЗНОСТЬДАТ(Т.ВремяВхода, Т.ВремяВыхода, СЕКУНДА)
КОНЕЦ КАК ДлительностьВСекундах
ИЗ
РегистрСведений.ВремяПрибытия КАК Т
Поскольку вопрос касается конфигурации Управление производственным предприятием (УПП), мы можем воспользоваться встроенными инструментами. В общем модуле ОбщегоНазначения существует полезная процедура РазобратьРазностьДат, которая позволяет получить разложенную разницу (дни, часы, минуты).
Пример вызова функции:
Лет = 0; Месяцев = 0; Дней = 0; Часов = 0; Минут = 0; Секунд = 0;
ОбщегоНазначения.РазложитьРазностьДат(ДатаВыхода, ДатаВхода, Лет, Месяцев, Дней, Часов, Минут, Секунд);
// Теперь переменные Часов и Минут содержат нужные нам значения
В завершение разберем важный совет по проектированию структуры регистра. Хранение колонки «Всего времени» строкой (например, "3:30") — это плохая практика. Строковые значения крайне сложно суммировать в отчетах или использовать для расчетов среднего времени пребывания.
Рекомендуемый подход:
ВремяВхода и ВремяВыхода как полный тип Дата (дата + время). Это избавит от всех проблем с переходом через сутки и позволит корректно считать время, даже если сотрудник пробыл на территории несколько дней.СекундыНаТерритории (тип Число).Такой подход обеспечит гибкость вашей системы: вы сможете легко построить отчет, например, «Суммарное время сотрудников за месяц», просто просуммировав числовое поле секунд и переведя итог в часы.
Мы рассмотрели основные способы вычисления разницы во времени в 1С. Выбор конкретного метода зависит от ваших задач: для простых расчетов в коде подойдет арифметическое вычитание, для сложных отчетов — запросы, а для типовых конфигураций — встроенные функции общих модулей.