Как в запросе 1С получить время из даты

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

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

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

Способ 1. Получение времени как объекта Дата с «пустым» числом

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

Рассмотрим конкретный пример кода:


ВЫБРАТЬ
    ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1), СЕКУНДА, РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(Таблица.ДатаДокумента, ДЕНЬ), Таблица.ДатаДокумента, СЕКУНДА)) КАК Время
ИЗ
    Документ.РеализацияТоваровУслуг КАК Таблица

Разберем по шагам с помощью bm Консоли запросов, что происходит в этой конструкции:

  1. Функция НАЧАЛОПЕРИОДА(..., ДЕНЬ) отсекает время, оставляя дату на начало дня (00:00:00).
  2. Функция РАЗНОСТЬДАТ вычисляет количество секунд, прошедших с начала дня до момента времени в документе.
  3. Функция ДОБАВИТЬКДАТЕ берет минимально возможную дату в системе ДАТАВРЕМЯ(1, 1, 1) и прибавляет к ней полученные секунды.

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

Способ 2. Расчет секунд или минут с начала дня (для группировок)

Если ваша задача — сгруппировать данные по времени или отсортировать их, иногда проще и быстрее использовать обычную арифметику. Мы можем вычислить время как числовое значение.

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


ВЫБРАТЬ
    ЧАС(Продажи.Период) * 3600 + МИНУТА(Продажи.Период) * 60 + СЕКУНДА(Продажи.Период) КАК СекундСНачалаДня,
    Продажи.СуммаОборота КАК Сумма
ИЗ
    РегистрНакопления.Продажи.Обороты КАК Продажи

Использование функций ЧАС, МИНУТА и СЕКУНДА позволяет получить числовые составляющие. Сложив их с соответствующими коэффициентами, мы получаем индекс времени. По такому полю очень удобно делать отборы, например: ГДЕ (ЧАС(Дата) * 60 + МИНУТА(Дата)) МЕЖДУ 480 И 1080 (отбор интервала с 08:00 до 18:00).

Способ 3. Преобразование времени в строку в запросе

Иногда требуется получить время именно строкой вида "ЧЧ:ММ:СС" прямо в запросе. Это самая сложная задача, так как функция ВЫРАЗИТЬ в 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" и вычисляем позицию символа, который нужно взять. Несмотря на свою работоспособность, мы рекомендуем использовать его только в самых крайних случаях, когда нет возможности обработать результат во встроенном языке или средствами СКД.

Способ 4. Использование возможностей СКД

Если вы разрабатываете отчет на Системе компоновки данных, то преобразовывать дату в запросе чаще всего не нужно. Система компоновки позволяет решить вопрос представления данных на уровне настроек оформления.

Выясним, как это сделать правильно:

  1. Оставьте в запросе обычное поле Дата.
  2. В настройках СКД на закладке «Наборы данных» найдите ваше поле.
  3. В колонке «Оформление» установите параметр «Формат».
  4. Укажите форматную строку ДФ=ЧЧ:мм:сс.

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

Оптимизация и производительность

Важно помнить о «подводных камнях» при работе с функциями времени в условиях запроса. Выясним основные правила:

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

Подводя итог, можно сказать: для расчетов и логики используйте метод с ДОБАВИТЬКДАТЕ к пустой дате, для простых группировок — функции ЧАС(), а для вывода пользователю — возможности оформления СКД.

← На главную