В процессе разработки отчетов или сложных выборок в 1С часто возникает задача: сгруппировать данные по времени суток, игнорируя конкретную дату. Например, нам нужно увидеть активность пользователей в течение дня за целый месяц, чтобы понять, в какие часы нагрузка на систему максимальна. Для этого необходимо все записи, сделанные в разные дни, привести к одной «эталонной» дате, сохранив при этом исходное время (часы, минуты, секунды). Рассмотрим, как это реализовать стандартными средствами языка запросов 1С.
Самый эффективный и распространенный способ — это вычисление количества секунд, прошедших с начала дня, и добавление этого количества к фиксированной «пустой» дате. Рассмотрим этот метод подробнее. В языке запросов 1С мы не можем просто «отрезать» дату, так как тип Дата всегда содержит обе составляющие. Поэтому наша задача — сделать дату у всех записей одинаковой.
Разберем логику по шагам:
НАЧАЛОПЕРИОДА.РАЗНОСТЬДАТ.ДОБАВИТЬКДАТЕ.Проанализируем пример кода, который реализует этот алгоритм:
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1), СЕКУНДА, РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(Регистр.Период, ДЕНЬ), Регистр.Период, СЕКУНДА)) КАК Время
ИЗ
РегистрНакопления.Продажи КАК Регистр
В данном примере мы используем ДАТАВРЕМЯ(1, 1, 1) в качестве базовой точки. Это позволяет нам получить результат типа Дата, где год, месяц и день всегда будут равны единице, а время будет соответствовать времени из поля Регистр.Период. Такое поле идеально подходит для группировки и сортировки в отчетах.
Если нам не требуется сохранять тип данных Дата, а нужно лишь получить числовые значения составляющих времени, мы можем воспользоваться встроенными функциями. Это полезно, когда время используется для математических расчетов или сложных условий.
Функции ЧАС, МИНУТА и СЕКУНДА принимают на вход дату и возвращают число. Посмотрим, как можно вычислить общее количество секунд с начала дня вручную:
ВЫБРАТЬ
ЧАС(Таблица.Период) * 3600 + МИНУТА(Таблица.Период) * 60 + СЕКУНДА(Таблица.Период) КАК ВремяВСекундах
ИЗ
Справочник.События КАК Таблица
Однако стоит учитывать, что собрать эти числа обратно в строку вида "18:39" или в тип Дата внутри запроса значительно сложнее, так как язык запросов 1С не поддерживает конкатенацию (сложение) строк и чисел произвольным образом. Именно поэтому первый метод с ДОБАВИТЬКДАТЕ считается более универсальным.
Иногда использование даты 01.01.0001 может быть неудобным, например, если внешние системы или СУБД (Microsoft SQL Server) некорректно обрабатывают даты ранее 1753 года в некоторых специфических сценариях. В таких случаях мы можем использовать любую «красивую» дату в качестве точки отсчета, например, 1 января 2000 года.
Выясним, как изменится наш запрос:
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(2000, 1, 1), СЕКУНДА, РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(Таблица.Период, ДЕНЬ), Таблица.Период, СЕКУНДА)) КАК ВремяДляГрафика
ИЗ
РегистрСведений.ЛогиДоступа КАК Таблица
Важный нюанс: при использовании СЕКУНДА в функции РАЗНОСТЬДАТ мы получаем максимальную точность. Если для вашей задачи (например, планирование посещений) достаточно точности до минуты, лучше использовать МИНУТА. Это снизит нагрузку при расчетах на больших объемах данных.
Зачастую требуется не просто выделить время, а сгруппировать события по интервалам, например, по 15 минут или по 1 часу. Для этого мы можем модифицировать формулу, добавив в нее математические преобразования. Рассмотрим, как округлить время до часа внутри запроса:
ВЫБРАТЬ
НАЧАЛОПЕРИОДА(Таблица.Период, ЧАС) КАК ЧасСобытия,
СУММА(Таблица.Сумма) КАК СуммаПродаж
ИЗ
Документ.ЧекиККМ КАК Таблица
ГРУППИРОВАТЬ ПО
НАЧАЛОПЕРИОДА(Таблица.Период, ЧАС)
Но если нам нужно сгруппировать данные по часам, игнорируя дату (то есть собрать все "9 утра" всех дней в одну строку), мы комбинируем методы:
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(2000, 1, 1), ЧАС, ЧАС(Таблица.Период)) КАК ЧасДня,
КОЛИЧЕСТВО(*) КАК КоличествоСобытий
ИЗ
РегистрСведений.ВходыВыходы КАК Таблица
ГРУППИРОВАТЬ ПО
ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(2000, 1, 1), ЧАС, ЧАС(Таблица.Период))
Если вы разрабатываете отчет на СКД, выделение времени можно выполнить не только в запросе, но и на уровне настроек полей набора данных. В СКД доступны функции языка выражений, которые работают аналогично функциям запроса.
Проанализируем преимущества использования Условного оформления в СКД. Если вам нужно просто показать пользователю время, не меняя саму дату в запросе, вы можете оставить поле Период как есть, но в настройках оформления задать формат даты ДФ=ЧЧ:мм. В этом случае:
Помните о часовых поясах: функции НАЧАЛОПЕРИОДА и РАЗНОСТЬДАТ на стороне сервера работают по времени сервера или UTC (в зависимости от настроек). Если ваша база распределена по разным регионам, перед выделением времени может потребоваться приведение периода к местному времени пользователя.
Подводя итог, можно сказать, что метод с использованием ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1,1,1)...) является «золотым стандартом» для разработчика 1С. Он обеспечивает сохранение типа данных, высокую точность и корректную работу механизмов сортировки и группировки в любых отчетах и динамических списках.