Как перевести количество секунд в дни, часы, минуты и секунды в 1С?

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

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

Рассмотрим подробно способы решения этой задачи в платформе 1С:Предприятие, разберем математический алгоритм деления, альтернативный вариант через форматирование дат, а также выясним особенности работы фоновых таймеров.

Способ 1. Математический расчет через целочисленное деление и остаток

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

Разберем алгоритм по шагам:

  1. Вычисляем количество полных дней: делим общее число секунд на 86 400 (количество секунд в одних сутках: 24 × 3600).
  2. Находим количество оставшихся часов: для этого делим общее количество секунд на 3600 и вычитаем количество уже учтенных часов в полных днях (Дней * 24), либо берем остаток от деления общего количества часов на 24.
  3. Определяем остаток секунд после вычитания полных часов через оператор % 3600.
  4. Рассчитываем минуты: делим оставшиеся секунды на 60.
  5. Получаем остаток секунд через оператор % 60.

Проанализируем пример кода на языке 1С:


// Исходные данные: общее количество секунд до нужного события
ОсталосьВремени = 90615; // Пример: 1 день, 1 час, 10 минут, 15 секунд

// 1. Вычисляем полные дни
Дней = Цел(ОсталосьВремени / (3600 * 24));

// 2. Вычисляем часы в пределах текущих суток
Часов = Цел(ОсталосьВремени / 3600) - (Дней * 24);

// 3. Получаем остаток секунд после вычета полных часов
СекОстМин = ОсталосьВремени % 3600;

// 4. Вычисляем минуты и итоговые секунды
Минут = Цел(СекОстМин / 60);
Секунд = СекОстМин % 60;

// Формируем строковое представление
РезультатТекстом = Строка(Дней) + " д. " + Строка(Часов) + " ч. " + Строка(Минут) + " мин. " + Строка(Секунд) + " сек.";

Существует также более наглядный вариант этого же алгоритма, выполняющий последовательный расчет остатков:


Дней = Цел(ОстатокСекунд / 86400);
ОстатокПослеДней = ОстатокСекунд % 86400;

Часов = Цел(ОстатокПослеДней / 3600);
ОстатокПослеЧасов = ОстатокПослеДней % 3600;

Минут = Цел(ОстатокПослеЧасов / 60);
Секунд = ОстатокПослеЧасов % 60;

Способ 2. Использование функции Формат() для небольших интервалов

Если гарантировано, что отображаемый временной интервал не превышает 31 день, можно применить прибавление разницы секунд к пустой дате '00010101000000' с последующим вызовом функции Формат().


ДатаТаймера = КонецГода(ТекущаяДата());
ТДата = ТекущаяДата();
ОстатокСекунд = ДатаТаймера - ТДата; // Получаем разницу в секундах

// Формируем представление через форматную строку
ОсталосьВремени = Формат('00010101000000' + ОстатокСекунд, "ДФ='d ""д."" H ""ч."" mm ""мин."" ss ""сек.""'");

Важная особенность: Спецификатор d в форматной строке выводит день месяца, а не общее количество прошедших дней. Если разница превысит 31 день (например, 100 дней), счетчик дней сбросится на начало нового месяца, и отображаемое значение станет некорректным. Для больших интервалов используйте только математический расчет из Способа 1.

Способ 3. Вычисление разности дат с помощью Запросов

Если расчет необходимо произвести в рамках выполнения сложной бизнес-логики на сервере, можно воспользоваться функцией языка запросов РАЗНОСТЬДАТ:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	РАЗНОСТЬДАТ(&ДатаВычитаемая, &ДатаИзКоторойВычитаем, СЕКУНДА) КАК РазностьСекунд";

Запрос.УстановитьПараметр("ДатаВычитаемая", ТекущаяДата());
Запрос.УстановитьПараметр("ДатаИзКоторойВычитаем", ЦелеваяДата);

Выборка = Запрос.Выполнить().Выгрузить();
ОстатокСекунд = Выборка[0].РазностьСекунд;

Особенности работы с таймером и процедурой ПодключитьОбработчикОжидания

Часто при создании таймеров на формах разработчики используют системный метод ПодключитьОбработчикОжидания() для обновления информации на экране каждую секунду. Однако при этом важно учитывать следующую специфику платформы:

  1. Нестрогий интервал выполнения: Метод ПодключитьОбработчикОжидания вызывается платформой только в момент состояния покоя (idle) клиентского приложения. Если пользователь активно редактирует данные, открывает формы или выполняет серверные вызовы, обработчик будет отложен и сработает позже релаксации системы.
  2. Накопление погрешности: Уменьшение счетчика на единицу при каждом тике (Счетчик = Счетчик - 1) приведёт к рассинхронизации реального времени и таймера.
  3. Правильное решение: Сохраняйте в переменной или реквизите формы фиксированную целевую дату события. При каждом срабатывании обработчика пересчитывайте остаток как ЦелеваяДата - ТекущаяДата().

Рассмотрим правильную реализацию таймера на форме:


&НаКлиенте
Процедура ПриОткрытии(Отказ)
    // Подключаем обработчик с интервалом в 1 секунду
    ПодключитьОбработчикОжидания("ОбновитьВремя", 1, Ложь);
КонецПроцедуры

&НаКлиенте
Процедура ОбновитьВремя()
    ОстатокСекунд = Объект.ЦелеваяДата - ТекущаяДата();
    
    Если ОстатокСекунд <= 0 Тогда
        ОтключитьОбработчикОжидания("ОбновитьВремя");
        Элементы.НадписьТаймер.Заголовок = "Время истекло!";
        Возврат;
    КонецЕсли;
    
    Дней = Цел(ОстатокСекунд / 86400);
    Часов = Цел((ОстатокСекунд % 86400) / 3600);
    Минут = Цел((ОстатокСекунд % 3600) / 60);
    Секунд = ОстатокСекунд % 60;
    
    Элементы.НадписьТаймер.Заголовок = Строка(Дней) + " д. " + Формат(Часов, "Ч(0)2") + ":" + Формат(Минут, "Ч(0)2") + ":" + Формат(Секунд, "Ч(0)2");
КонецПроцедуры
← На главную