При разработке отчетов в системе компоновки данных (СКД) программисты часто сталкиваются с задачей вывода отработанного времени. Основная сложность заключается в том, что время в формате «часы.минуты» (например, 8.45 — это 8 часов 45 минут) невозможно складывать как обычные числа. Математически 8.45 + 8.45 даст 16.90, хотя с точки зрения времени мы ожидаем увидеть 17 часов 30 минут. В этой статье мы разберем, как избежать накопления ошибок и правильно настроить ресурсы в СКД.
Разберем типичную ситуацию: у нас есть данные в секундах или дробных часах. Если мы попытаемся преобразовать их в формат «ЧЧ.ММ» (где ММ — это именно минуты) до этапа суммирования итогов, мы получим неверный результат. Рассмотрим, почему это происходит. Проблема заключается в разнице между десятичной дробью и временным интервалом. В часе 60 минут, а не 100. Следовательно, любое сложение «псевдо-десятичных» чисел (где после запятой стоят минуты) приведет к тому, что итог будет отличаться от реального на десятки часов в масштабе месяца.
Рассмотрим по шагам профессиональные подходы к решению этой задачи.
Это самый надежный способ. Мы будем хранить и суммировать время в секундах (целое число), а преобразовывать его в читаемый вид только в момент отображения пользователю. Проанализируем, как это настроить в СКД:
РАЗНОСТЬДАТ(ДатаНачала, ДатаОкончания, СЕКУНДА). Назовем это поле ВремяВСекундах.ВремяВСекундах и в выражении пишем обычную сумму: Сумма(ВремяВСекундах).В колонке «Выражение представления» для поля ВремяВСекундах мы можем прописать формулу, которая превратит секунды в формат «ЧЧ:ММ»:
Цел(ВремяВСекундах / 3600) + ":" + Формат((ВремяВСекундах % 3600) / 60, "ЧЦ=2; ЧВН=; ЧГ=0")
Этот метод гарантирует, что математика итогов останется безупречной, так как система складывает целые числа (секунды), а не дроби.
Если нам удобнее работать с часами в десятичном виде, важно помнить правило: 15 минут — это 0.25 часа, 30 минут — 0.5, а 45 минут — 0.75. Если переводить время по формуле Минуты / 60, то такие числа можно суммировать обычным способом.
Посмотрим на пример функции, которую предложил один из участников обсуждения для преобразования времени в «десятично-визуальный» формат:
Функция Время(ВрВЧасах) Экспорт
Если не ТипЗнч(ВрВЧасах) = Тип("Число") Тогда
Возврат 0;
КонецЕсли;
ЧЧ = Цел(ВрВЧасах);
ММ = Окр(60 * (ВрВЧасах - ЧЧ));
Результат = ЧЧ + ММ / 100; // Превращаем 8.75 в 8.45
Возврат Результат;
КонецФункции
Внимание! Эту функцию можно использовать только для вывода. Если вы используете её результат для суммирования в ресурсах, вы получите ошибку. Правильный путь: в ресурсах суммируем точное значение ВрВЧасах (например, 8.75), а в выражении представления вызываем эту функцию для красоты.
Часто программисты пытаются использовать формат даты ДФ=ЧЧ:мм. Но у этого метода есть существенный недостаток: как только сумма времени превышает 24 часа, счетчик обнуляется (25 часов превратятся в 01:00).
Чтобы корректно отобразить, например, 150 часов 30 минут в общих итогах, проанализируем выражение в ресурсах СКД. Вы можете использовать следующую конструкцию в поле «Выражение» на вкладке «Ресурсы»:
Строка(Цел(Сумма(ВремяВСекундах) / 3600)) + ":" + Формат((Сумма(ВремяВСекундах) % 3600) / 60, "ЧЦ=2; ЧВН=; ЧГ=0")
Здесь мы принудительно вычисляем количество целых часов (их может быть сколько угодно) и добавляем к ним остаток минут, отформатированный до двух знаков с лидирующим нулем.
Как было отмечено в ходе обсуждения, в агрегатных функциях СКД можно использовать РазностьДат. Это бывает полезно, когда данные в отчете сгруппированы по периодам, и вам нужно посчитать общую длительность между самым началом и самым концом периода.
Однако для суммирования отдельных интервалов (например, нескольких записей за день) лучше всего подходит суммирование предварительно вычисленной разницы в секундах. Это исключает влияние микросекундных расхождений при расчете больших объемов данных.
Подведем итоги нашего анализа. Для того чтобы ваши отчеты всегда показывали правильное время, придерживайтесь следующих правил:
ИмяВашегоМодуля.ФорматВремени(Сумма(ВремяВСекундах)).Таким образом, мы рассмотрели ситуацию, когда внешняя простота (использование чисел типа 8.45) ведет к программным ошибкам, и выяснили, как с помощью встроенных механизмов СКД (Ресурсы и Выражения представления) добиться математической точности и удобства для конечного пользователя.