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

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

При разработке отчетов и обработок в платформе 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. Функция языка запросов РАЗНОСТЬДАТ(Дата1, Дата2, Периодичность) вычисляет разницу как Дата2 - Дата1 (первый параметр — начальная дата, второй — конечная).
  2. Если передать исходную дату Граница первым параметром, а НАЧАЛОПЕРИОДА(Граница, ДЕНЬ) вторым, то из меньшей даты вычитается большая, и результат получается отрицательным со знаком минус.
  3. Платформа 1С не поддерживает даты ранее 01.01.0001 00:00:00. При попытке вычесть отрицательное количество секунд из минимальной даты СУБД сбрасывает значение в крайнюю левую границу — 01.01.0001 00:00:00.

Способ 1. Исправление порядка аргументов в функции РАЗНОСТЬДАТ

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

Разберем готовый фрагмент запроса:


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

Важный момент: функция РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(Граница, ДЕНЬ), Граница, СЕКУНДА) корректно возвращает число секунд от полуночи (например, для 17:00:00 это будет 61200 секунд), которые затем успешно прибавляются к пустой дате 01.01.0001 00:00:00.

Способ 2. Вычисление времени через функции ЧАС, МИНУТА и СЕКУНДА

В языке запросов 1С доступны функции извлечения компонентов даты: ЧАС(), МИНУТА() и СЕКУНДА(). С их помощью можно вычислить общее смещение в секундах математически:


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

Также можно выполнить последовательное добавление каждого компонента времени без перемножения:


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

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

Если задача решается вне текста запроса (в модуле объекта, формы или общего назначения), приведение даты к нулевому дню выполняется гораздо проще и нагляднее.

Рассмотрим два варианта на встроенном языке:

  1. Через конструктор даты: Время = Дата(1, 1, 1, Час(Граница), Минута(Граница), Секунда(Граница));
  2. Через разницу в секундах: Время = '00010101000000' + (Граница - НачалоДня(Граница));

Рекомендации по отображению и фильтрации

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

  1. Только для вывода в отчет (СКД): если требуется просто показать пользователю время без даты, преобразовывать значение в запросе не нужно. В настройках выбранных полей или условного оформления задайте форматную строку ДФ=ЧЧ:мм:сс (или ДФ=HH:mm:ss).
  2. Для фильтрации по интервалу времени: если необходимо отобрать документы, проведенные, например, с 09:00:00 до 18:00:00 независимо от дня, эффективнее сравнивать напрямую количество секунд от начала суток:
    
    ГДЕ
        РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(Таблица.Дата, ДЕНЬ), Таблица.Дата, СЕКУНДА) МЕЖДУ 32400 И 64800
    
← На главную