В процессе разработки на платформе 1С:Предприятие 8 часто возникает задача расчета длительности процесса. Например, нужно вычислить время, затраченное на выполнение заказа, имея время старта и время финиша. Основная сложность для начинающих разработчиков заключается в том, что при вычитании одной даты из другой 1С возвращает результат в секундах (число), а не в формате времени. Разберем подробно, как правильно обработать эти данные и отобразить их пользователю в удобном виде.
Для начала проанализируем, как платформа воспринимает тип данных Дата. В 1С дата включает в себя и календарный день, и время. Если мы вычитаем ВремяСтарта из ВремяФиниша, мы получаем количество секунд, прошедших между этими двумя событиями. Рассмотрим простейший пример:
// Допустим:
// ВремяСтарта = 01.01.2023 10:00:00
// ВремяФиниша = 01.01.2023 10:01:30
Разница = Объект.ВремяФиниша - Объект.ВремяСтарта;
// Результат будет равен 90 (секунд)
Проблема автора темы заключалась в том, что он пытался присвоить это число (90) реквизиту с типом Дата, ожидая увидеть «00:01:30», но система не может автоматически преобразовать число в дату без дополнительных инструкций.
Самый быстрый способ получить результат в виде времени (если разница не превышает 24 часа) — это прибавить полученную разницу в секундах к началу летоисчисления (01.01.0001 00:00:00). Рассмотрим, как это реализовать в коде:
&НаСервере
Процедура РасчётФиниша()
Объект.ВремяФиниша = ТекущаяДата();
// Вычисляем разницу и прибавляем её к пустой дате
// Дата(1, 1, 1) — это конструктор, создающий дату 01 января 0001 года
Объект.ВремяЗатрачено = Дата(1, 1, 1) + (Объект.ВремяФиниша - Объект.ВремяСтарта);
КонецПроцедуры
Важный момент: В конструкторе Дата(Год, Месяц, День) параметры «1, 1, 1» означают минимально возможную дату в системе. Когда мы прибавляем к ней секунды, мы получаем новую дату, где время будет соответствовать нашей разнице. Если в свойствах реквизита ВремяЗатрачено на форме установлен «Состав даты: Время», пользователь увидит аккуратные часы, минуты и секунды.
Если нам нужно вывести длительность не просто как время, а, например, строкой «2 ч. 15 мин.», или если длительность может превышать сутки, метод с «пустой датой» нам не подойдет (так как после 24 часов дата сменится на 02.01.0001 и время снова начнет отсчет с нуля). В таком случае проанализируем алгоритм ручного расчета:
&НаКлиенте
Процедура РассчитатьРазницуСтрокой(РазницаВСекундах)
ВсегоЧасов = Цел(РазницаВСекундах / 3600);
ОстатокСекунд = РазницаВСекундах % 3600;
ВсегоМинут = Цел(ОстатокСекунд / 60);
Секунды = ОстатокСекунд % 60;
Сообщить("Затрачено времени: " + ВсегоЧасов + " ч. " + ВсегоМинут + " мин. " + Секунды + " сек.");
КонецПроцедуры
Здесь мы используем оператор Цел() для получения целой части от деления и оператор % (остаток от деления). Это универсальный способ, который работает корректно при любых временных интервалах.
Выясним причину возможной ошибки, если в реквизитах хранится только время (без даты). Если работа началась в 23:00 одного дня, а закончилась в 01:00 следующего, и в реквизитах даты стоят одинаковые (по умолчанию 0001-01-01), то вычитание даст отрицательный результат. Чтобы этого избежать, используем проверку:
Разница = Объект.ВремяФиниша - Объект.ВремяСтарта;
Если Разница < 0 Тогда
// Если финиш меньше старта, значит наступили новые сутки (добавляем 24 часа в секундах)
Разница = Разница + 86400;
КонецЕсли;
Объект.ВремяЗатрачено = Дата(1, 1, 1) + Разница;
Рассмотрим ситуацию, когда нам нужно программно получить красивое представление времени. Для этого в 1С предусмотрена функция Формат(). Если наш реквизит уже имеет тип Дата, мы можем управлять его визуализацией:
Пример использования в коде:
ТекстДляПользователя = Формат(Объект.ВремяЗатрачено, "ДФ=ЧЧ:мм");
// Результат будет строкой, например: "01:45"
В исходном сообщении автор выполнял расчеты на сервере. Однако операции с датами — это легкие арифметические действия. Чтобы интерфейс работал быстрее и не было лишних обращений к серверу (мигания формы, задержек), рекомендуется перенести расчет в клиентскую процедуру &НаКлиенте. Функция ТекущаяДата() работает и на клиенте, возвращая время компьютера пользователя.
Если в будущем вы планируете строить отчеты по этим данным (например, «Суммарное время всех заказов за месяц»), то хранить «Затраченное время» в типе Дата не совсем удобно, так как даты нельзя складывать между собой в запросах. В профессиональной разработке рекомендуется:
Таким образом, мы разобрали несколько способов решения задачи: от самого простого (прибавление к начальной дате) до универсального математического метода. Выбор конкретного подхода зависит от бизнес-требований к вашему документу и возможной длительности процессов.