В практике разработки на платформе 1С:Предприятие часто возникает задача вычисления длительности или перевода времени, представленного в текстовом виде (например, "12:20:54"), в общее количество секунд. Это требуется при расчете хронометража операций, анализе логов оборудования, обработке данных телефонии или тарификации.
Разберем по шагам наиболее популярные и эффективные способы решения этой задачи, проанализируем их плюсы, минусы и скрытые подводные камни.
Рассмотрим классический математический подход: разобьем строку по разделителю-двоеточию ":", приведем полученные часы, минуты и секунды к числу и вычислим итоговую сумму по формуле: Секунды = Часы * 3600 + Минуты * 60 + Секунды.
В современных версиях платформы 1С:Предприятие (начиная с релиза 8.3.6) для этого предназначена штатная функция СтрРазделить(). В более ранних версиях или при использовании Библиотеки стандартных подсистем можно использовать функцию ОбщегоНазначения.РазложитьСтрокуВМассивПодстрок().
Посмотрим на пример кода с использованием штатной функции платформы:
ВремяСтрокой = "12:20:54";
ЧастиВремени = СтрРазделить(ВремяСтрокой, ":");
Если ЧастиВремени.Количество() = 3 Тогда
КоличествоСекунд = Число(ЧастиВремени[0]) * 3600
+ Число(ЧастиВремени[1]) * 60
+ Число(ЧастиВремени[2]);
Иначе
КоличествоСекунд = 0;
КонецЕсли;
Главное достоинство этого метода заключается в универсальности: он без ошибок обрабатывает не только время суток в пределах 24 часов, но и любые интервалы времени и хронометражи (например, длительность работы станка "150:45:10" или таймер задачи).
Если формат входящей строки гарантированно жесткий и всегда содержит лидирующие нули (ровно 8 символов формата "ЧЧ:ММ:СС"), можно обойтись без создания массивов и разобрать строку функциями работы с подстроками. Разберем реализацию этого алгоритма:
ВремяСтрокой = "12:20:54";
КоличествоСекунд = Число(Сред(ВремяСтрокой, 1, 2)) * 3600
+ Число(Сред(ВремяСтрокой, 4, 2)) * 60
+ Число(Сред(ВремяСтрокой, 7, 2));
Такой вариант работает быстро, однако требует строгого формата. Если на вход может поступить значение без лидирующего нуля (например, "1:20:54"), позиции символов сместятся, что приведет к неверному результату. Для нормализации строки в подобных случаях перед разбором применяют дополнение нулем слева:
ВремяСтрокой = "1:20:54";
Если СтрДлина(ВремяСтрокой) = 7 Тогда
ВремяСтрокой = "0" + ВремяСтрокой;
КонецЕсли;
КоличествоСекунд = Число(Сред(ВремяСтрокой, 1, 2)) * 3600
+ Число(Сред(ВремяСтрокой, 4, 2)) * 60
+ Число(Сред(ВремяСтрокой, 7, 2));
Платформа 1С:Предприятие при вычитании одного значения типа Дата из другого возвращает разницу в секундах. Мы можем сформировать фиктивную дату с указанным временем и вычесть из нее начало дня или пустую дату.
Посмотрим на пример со смещением относительно начала дня:
ВремяСтрокой = "12:20:54";
ДатаИВремя = Дата("20000101" + СтрЗаменить(ВремяСтрокой, ":", ""));
КоличествоСекунд = ДатаИВремя - '20000101000000';
Или через приведение к текущей дате и расчет от начала суток:
ВремяСтрокой = "12:20:54";
ДатаИВремя = Дата(Формат(ТекущаяДата(), "ДФ=yyyy.MM.dd") + " " + ВремяСтрокой);
КоличествоСекунд = ДатаИВремя - НачалоДня(ДатаИВремя);
Критическое ограничение: этот подход применим исключительно к времени суток в пределах одного дня. Если значение часов равно 24 или больше (например, длительность "26:00:00"), либо минуты превышают 59, конструктор Дата() вызовет аварийную ошибку времени выполнения, так как тип Дата в 1С валидирует диапазоны календарного времени.
В ветке обсуждения был предложен математический трюк с трансформацией строки в арифметическое выражение со скобками и последующим расчетом через Вычислить():
ВремяСтрокой = "12:20:54";
// Преобразуем "12:20:54" в выражение вида "((12)*60+20)*60+54"
Выражение = "((" + СтрЗаменить(ВремяСтрокой, ":", ")*60+")");
КоличествоСекунд = Число(Вычислить(Выражение));
Проанализируем этот прием: несмотря на краткость записи в одну строку, использовать его в промышленном коде крайне не рекомендуется по двум причинам:
Вычислить() может привести к выполнению вредоносного кода 1С.Часто программисты интересуются, можно ли преобразовать такую строку в секунды непосредственно внутри запроса 1С. Выясним причину сложностей: язык запросов 1С не поддерживает строковое деление, операции Число() и приведение строки к дате через ВЫРАЗИТЬ.
Выполнить такой разбор в запросе можно только крайне громоздкими конструкциями с функцией ПОДСТРОКА и многочисленными условиями ВЫБОР КОГДА. Поэтому оптимальным решением всегда является предварительный перевод строки в число на встроенном языке с последующей передачей готового значения секунд в параметры запроса или во временную таблицу.
Подведем итог: для надежного и безопасного кода наилучшим выбором является Способ 1 с использованием СтрРазделить(). Он защищен от ошибок переполнения часов свыше 24, легко читается и не подвержен уязвимостям безопасности.