Как правильно рассчитать и вывести итоги по времени (часам и минутам) в отчете СКД?

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

При разработке отчетов в системе компоновки данных (СКД) программисты часто сталкиваются с задачей вывода отработанного времени. Основная сложность заключается в том, что время в формате «часы.минуты» (например, 8.45 — это 8 часов 45 минут) невозможно складывать как обычные числа. Математически 8.45 + 8.45 даст 16.90, хотя с точки зрения времени мы ожидаем увидеть 17 часов 30 минут. В этой статье мы разберем, как избежать накопления ошибок и правильно настроить ресурсы в СКД.

Проблема «визуального» времени и накопления ошибок

Разберем типичную ситуацию: у нас есть данные в секундах или дробных часах. Если мы попытаемся преобразовать их в формат «ЧЧ.ММ» (где ММ — это именно минуты) до этапа суммирования итогов, мы получим неверный результат. Рассмотрим, почему это происходит. Проблема заключается в разнице между десятичной дробью и временным интервалом. В часе 60 минут, а не 100. Следовательно, любое сложение «псевдо-десятичных» чисел (где после запятой стоят минуты) приведет к тому, что итог будет отличаться от реального на десятки часов в масштабе месяца.

Рассмотрим по шагам профессиональные подходы к решению этой задачи.

Вариант 1. Использование секунд как эталонной единицы измерения

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

  1. В запросе: Получаем разность дат в секундах. Например, используя функцию РАЗНОСТЬДАТ(ДатаНачала, ДатаОкончания, СЕКУНДА). Назовем это поле ВремяВСекундах.
  2. На вкладке «Ресурсы»: Добавляем поле ВремяВСекундах и в выражении пишем обычную сумму: Сумма(ВремяВСекундах).
  3. Настройка отображения: Чтобы пользователь не видел огромные числа, нам нужно настроить «Выражение представления» для этого поля.

В колонке «Выражение представления» для поля ВремяВСекундах мы можем прописать формулу, которая превратит секунды в формат «ЧЧ:ММ»:


Цел(ВремяВСекундах / 3600) + ":" + Формат((ВремяВСекундах % 3600) / 60, "ЧЦ=2; ЧВН=; ЧГ=0")

Этот метод гарантирует, что математика итогов останется безупречной, так как система складывает целые числа (секунды), а не дроби.

Вариант 2. Работа с точными десятичными дробями

Если нам удобнее работать с часами в десятичном виде, важно помнить правило: 15 минут — это 0.25 часа, 30 минут — 0.5, а 45 минут — 0.75. Если переводить время по формуле Минуты / 60, то такие числа можно суммировать обычным способом.

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


Функция Время(ВрВЧасах) Экспорт
    Если не ТипЗнч(ВрВЧасах) = Тип("Число") Тогда 
        Возврат 0; 
    КонецЕсли;
    ЧЧ = Цел(ВрВЧасах);
    ММ = Окр(60 * (ВрВЧасах - ЧЧ));
    Результат = ЧЧ + ММ / 100; // Превращаем 8.75 в 8.45
    Возврат Результат;
КонецФункции

Внимание! Эту функцию можно использовать только для вывода. Если вы используете её результат для суммирования в ресурсах, вы получите ошибку. Правильный путь: в ресурсах суммируем точное значение ВрВЧасах (например, 8.75), а в выражении представления вызываем эту функцию для красоты.

Вариант 3. Решение проблемы «Более 24 часов» в итогах

Часто программисты пытаются использовать формат даты ДФ=ЧЧ:мм. Но у этого метода есть существенный недостаток: как только сумма времени превышает 24 часа, счетчик обнуляется (25 часов превратятся в 01:00).

Чтобы корректно отобразить, например, 150 часов 30 минут в общих итогах, проанализируем выражение в ресурсах СКД. Вы можете использовать следующую конструкцию в поле «Выражение» на вкладке «Ресурсы»:


Строка(Цел(Сумма(ВремяВСекундах) / 3600)) + ":" + Формат((Сумма(ВремяВСекундах) % 3600) / 60, "ЧЦ=2; ЧВН=; ЧГ=0")

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

Вариант 4. Использование агрегатной функции РазностьДат в ресурсах

Как было отмечено в ходе обсуждения, в агрегатных функциях СКД можно использовать РазностьДат. Это бывает полезно, когда данные в отчете сгруппированы по периодам, и вам нужно посчитать общую длительность между самым началом и самым концом периода.

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

Итоги и рекомендации

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

  1. Первичность секунд: Всегда старайтесь получать время в секундах на уровне запроса. Это «честное» число, которое 1С складывает без ошибок округления.
  2. Разделяйте значение и представление: Значение (то, что СКД суммирует) должно быть числом (секунды или десятичная дробь 8.75). Представление (то, что видит глаз пользователя) может быть строкой «08:45».
  3. Вычисляемые поля: Используйте вкладку «Вычисляемые поля» для создания промежуточных расчетов, но агрегацию (суммирование) делайте строго на вкладке «Ресурсы».
  4. Общие модули: Если формула перевода секунд в формат «ЧЧ:ММ» кажется вам слишком громоздкой для СКД, вынесите ее в общий модуль. Тогда в поле представления можно будет написать коротко: ИмяВашегоМодуля.ФорматВремени(Сумма(ВремяВСекундах)).

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

← На главную