В процессе разработки на платформе 1С часто возникает задача выделить время из переменной типа Дата непосредственно в запросе. Это необходимо для группировки данных по часам, фильтрации документов по определенному интервалу внутри дня (например, анализ вечерних продаж) или для вывода времени в отчеты без даты. Поскольку тип Дата в 1С всегда содержит и дату, и время, задача сводится к «обнулению» календарной части или получению числового эквивалента времени.
В данной статье мы разберем несколько эффективных методов решения этой задачи, проанализируем их производительность и выясним, какой способ лучше выбрать в зависимости от ваших целей.
Этот метод считается наиболее корректным, если вам нужно получить результат в формате «Дата», чтобы использовать его для сравнения или последующего форматирования. Суть заключается в том, чтобы вычислить разницу в секундах между началом дня и искомой датой, а затем добавить это количество секунд к «пустой» дате (01.01.0001).
Рассмотрим конкретный пример кода:
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1), СЕКУНДА, РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(Таблица.ДатаДокумента, ДЕНЬ), Таблица.ДатаДокумента, СЕКУНДА)) КАК Время
ИЗ
Документ.РеализацияТоваровУслуг КАК Таблица
Разберем по шагам с помощью bm Консоли запросов, что происходит в этой конструкции:
НАЧАЛОПЕРИОДА(..., ДЕНЬ) отсекает время, оставляя дату на начало дня (00:00:00).РАЗНОСТЬДАТ вычисляет количество секунд, прошедших с начала дня до момента времени в документе.ДОБАВИТЬКДАТЕ берет минимально возможную дату в системе ДАТАВРЕМЯ(1, 1, 1) и прибавляет к ней полученные секунды.В результате мы получаем значение, где год, месяц и день равны единице, а время в точности соответствует исходному документу. Это позволяет корректно сравнивать время разных событий, независимо от того, в какие дни они произошли.
Если ваша задача — сгруппировать данные по времени или отсортировать их, иногда проще и быстрее использовать обычную арифметику. Мы можем вычислить время как числовое значение.
Проанализируем ситуацию через управляемую консоль запросов: нам нужно понять нагрузку на склад в течение суток. Для этого мы можем получить смещение в секундах:
ВЫБРАТЬ
ЧАС(Продажи.Период) * 3600 + МИНУТА(Продажи.Период) * 60 + СЕКУНДА(Продажи.Период) КАК СекундСНачалаДня,
Продажи.СуммаОборота КАК Сумма
ИЗ
РегистрНакопления.Продажи.Обороты КАК Продажи
Использование функций ЧАС, МИНУТА и СЕКУНДА позволяет получить числовые составляющие. Сложив их с соответствующими коэффициентами, мы получаем индекс времени. По такому полю очень удобно делать отборы, например: ГДЕ (ЧАС(Дата) * 60 + МИНУТА(Дата)) МЕЖДУ 480 И 1080 (отбор интервала с 08:00 до 18:00).
Иногда требуется получить время именно строкой вида "ЧЧ:ММ:СС" прямо в запросе. Это самая сложная задача, так как функция ВЫРАЗИТЬ в 1С не умеет конвертировать числа или даты в строки. Здесь на помощь приходит «магия» функции ПОДСТРОКА.
Давайте посмотрим на пример формирования строки времени (часы и минуты):
ВЫБРАТЬ
ПОДСТРОКА("0123456789", ЧАС(Т.Дата) / 10 + 1, 1) +
ПОДСТРОКА("0123456789", СЕКУНДА(ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1), СЕКУНДА, 6 * ЧАС(Т.Дата))) / 6 + 1, 1) +
":" +
ПОДСТРОКА("0123456789", МИНУТА(Т.Дата) / 10 + 1, 1) +
ПОДСТРОКА("0123456789", СЕКУНДА(ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1), СЕКУНДА, 6 * МИНУТА(Т.Дата))) / 6 + 1, 1) КАК ВремяСтрокой
ИЗ
Справочник.Номенклатура КАК Т
Важное примечание: Этот метод крайне громоздкий и тяжело читается. Мы используем строку-шаблон "0123456789" и вычисляем позицию символа, который нужно взять. Несмотря на свою работоспособность, мы рекомендуем использовать его только в самых крайних случаях, когда нет возможности обработать результат во встроенном языке или средствами СКД.
Если вы разрабатываете отчет на Системе компоновки данных, то преобразовывать дату в запросе чаще всего не нужно. Система компоновки позволяет решить вопрос представления данных на уровне настроек оформления.
Выясним, как это сделать правильно:
Дата.ДФ=ЧЧ:мм:сс.В этом случае 1С будет хранить полноценную дату (что важно для сортировки), но пользователь увидит только время. Это наиболее производительный и правильный с точки зрения архитектуры подход.
Важно помнить о «подводных камнях» при работе с функциями времени в условиях запроса. Выясним основные правила:
ГДЕ РАЗНОСТЬДАТ(...) МЕЖДУ ..., СУБД не сможет использовать индекс по полю Дата. На больших таблицах (миллионы строк) такой запрос будет работать крайне медленно.СекундыСНачалаДня (тип Число). Заполняйте его при записи. В запросе фильтрация по индексированному числовому полю будет выполняться мгновенно.ЧАС и МИНУТА по-разному транслируются в SQL Server и PostgreSQL. Старайтесь избегать чрезмерно вложенных вычислений внутри ВЫБОР...КОГДА в секции ГДЕ.Подводя итог, можно сказать: для расчетов и логики используйте метод с ДОБАВИТЬКДАТЕ к пустой дате, для простых группировок — функции ЧАС(), а для вывода пользователю — возможности оформления СКД.