При разработке отчетов и обработок в платформе 1С:Предприятие часто возникает задача отделить дату от времени. Например, требуется сгруппировать события по времени суток независимо от конкретного дня или привести поле к виду 01.01.0001 17:00:00 из исходного значения 08.01.2018 17:00:00. Поскольку в 1С тип Дата всегда содержит и дату, и время, отдельного типа «Время» не существует, а пустая дата представляется как 01.01.0001 00:00:00.
Рассмотрим, почему при стандартных попытках вычисления времени в запросе может возвращаться 01.01.0001 00:00:00, разберем причину ошибки и изучим все корректные варианты решения.
Посмотрим на конструкцию, которую часто пытаются применить в тексте запроса:
ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1), СЕКУНДА, РАЗНОСТЬДАТ(Граница, НАЧАЛОПЕРИОДА(Граница, ДЕНЬ), СЕКУНДА))
В результате такого выражения возвращается 01.01.0001 00:00:00. Проанализируем причину такого поведения:
РАЗНОСТЬДАТ(Дата1, Дата2, Периодичность) вычисляет разницу как Дата2 - Дата1 (первый параметр — начальная дата, второй — конечная).Граница первым параметром, а НАЧАЛОПЕРИОДА(Граница, ДЕНЬ) вторым, то из меньшей даты вычитается большая, и результат получается отрицательным со знаком минус.01.01.0001 00:00:00. При попытке вычесть отрицательное количество секунд из минимальной даты СУБД сбрасывает значение в крайнюю левую границу — 01.01.0001 00:00:00.Для того чтобы получить положительное количество секунд, прошедших от начала дня до текущего момента, необходимо поменять аргументы местами: начальной датой должно быть начало дня, а конечной — само значение поля.
Разберем готовый фрагмент запроса:
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(
ДАТАВРЕМЯ(1, 1, 1),
СЕКУНДА,
РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(Таблица.Граница, ДЕНЬ), Таблица.Граница, СЕКУНДА)
) КАК ВремяСобытия
ИЗ
Документ.РегистрацияСобытий КАК Таблица
Важный момент: функция РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(Граница, ДЕНЬ), Граница, СЕКУНДА) корректно возвращает число секунд от полуночи (например, для 17:00:00 это будет 61200 секунд), которые затем успешно прибавляются к пустой дате 01.01.0001 00:00:00.
В языке запросов 1С доступны функции извлечения компонентов даты: ЧАС(), МИНУТА() и СЕКУНДА(). С их помощью можно вычислить общее смещение в секундах математически:
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(
ДАТАВРЕМЯ(1, 1, 1),
СЕКУНДА,
ЧАС(Таблица.Граница) * 3600 + МИНУТА(Таблица.Граница) * 60 + СЕКУНДА(Таблица.Граница)
) КАК ВремяСобытия
ИЗ
Документ.РегистрацияСобытий КАК Таблица
Также можно выполнить последовательное добавление каждого компонента времени без перемножения:
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(
ДОБАВИТЬКДАТЕ(
ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1), ЧАС, ЧАС(Таблица.Граница)),
МИНУТА,
МИНУТА(Таблица.Граница)
),
СЕКУНДА,
СЕКУНДА(Таблица.Граница)
) КАК ВремяСобытия
ИЗ
Документ.РегистрацияСобытий КАК Таблица
Если задача решается вне текста запроса (в модуле объекта, формы или общего назначения), приведение даты к нулевому дню выполняется гораздо проще и нагляднее.
Рассмотрим два варианта на встроенном языке:
Время = Дата(1, 1, 1, Час(Граница), Минута(Граница), Секунда(Граница));
Время = '00010101000000' + (Граница - НачалоДня(Граница));
Выясним, когда действительно необходимо модифицировать дату в запросе, а когда лучше применить другие механизмы платформы:
ДФ=ЧЧ:мм:сс (или ДФ=HH:mm:ss).
ГДЕ
РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(Таблица.Дата, ДЕНЬ), Таблица.Дата, СЕКУНДА) МЕЖДУ 32400 И 64800