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

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

При работе с языком запросов 1С часто возникает задача привести произвольное значение даты и времени к началу текущего дня (то есть установить время в 00:00:00). Рассмотрим подробнее, как правильно решить эту задачу, а также разберем важные нюансы, связанные с производительностью и обработкой сложных типов данных.

Основной способ: функция НАЧАЛОПЕРИОДА

Для получения даты на начало дня в языке запросов 1С предназначена встроенная функция НАЧАЛОПЕРИОДА. В качестве аргументов функция принимает исходное поле с датой и тип периода, к началу которого требуется привести значение.

Синтаксис функции выглядит следующим образом:

НАЧАЛОПЕРИОДА(ИсходнаяДата, ДЕНЬ)

Посмотрим на пример использования функции в реальном запросе:


ВЫБРАТЬ
    Продажи.Ссылка КАК Документ,
    Продажи.Дата КАК ДатаДокумента,
    НАЧАЛОПЕРИОДА(Продажи.Дата, ДЕНЬ) КАК ДатаНаНачалоДня
ИЗ
    Документ.Продажи КАК Продажи

В результате выполнения такого запроса поле ДатаНаНачалоДня будет содержать дату документа со временем 00:00:00.

Работа с составными типами и значениями NULL

Проанализируем ситуацию, когда исходное поле имеет составной тип данных (например, может содержать не только дату, но и строку или ссылку) либо возвращает NULL в результате левого или правого соединения таблиц. В таких случаях вызов функции НАЧАЛОПЕРИОДА может привести к ошибке «Неверные параметры "НАЧАЛОПЕРИОДА"».

Чтобы избежать ошибок, разберем по шагам правильную обработку таких полей:

  1. Если поле может содержать NULL, обернем его в функцию ЕСТЬNULL.
  2. Если поле составного типа, приведем его к типу ДАТА с помощью конструкции ВЫРАЗИТЬ.

Пример безопасного вызова функции:


НАЧАЛОПЕРИОДА(ЕСТЬNULL(ВЫРАЗИТЬ(Таблица.ПолеСоставногоТипа КАК ДАТА), ДАТАВРЕМЯ(1, 1, 1)), ДЕНЬ)

Если исходная дата является пустой (0001-01-01 / ДАТАВРЕМЯ(1, 1, 1)), функция НАЧАЛОПЕРИОДА вернет исходную пустую дату. Если в аргумент передается значение NULL, результатом работы функции также станет NULL.

Оптимизация производительности и отборы в секции ГДЕ

Выясним причину возможного замедления запросов при использовании функции в условиях отбора. Использование конструкции НАЧАЛОПЕРИОДА(Таблица.Дата, ДЕНЬ) в секции ГДЕ блокирует использование индексов СУБД по полю даты. В результате вместо точечного поиска выполняется полное сканирование таблицы, что существенно снижает скорость работы системы на больших объемах данных.

Важная рекомендация: не оборачивайте поле таблицы в функцию в секции ГДЕ. Вместо этого заранее подготавливайте граничные даты на стороне встроенного языка 1С и передавайте их в запрос в качестве параметров через оператор МЕЖДУ:


// В коде на встроенном языке:
Запрос.УстановитьПараметр("ДатаНачала", НачалоДня(ИсходнаяДата));
Запрос.УстановитьПараметр("ДатаКонца", КонецДня(ИсходнаяДата));

// В тексте запроса:
ГДЕ
    Таблица.Дата МЕЖДУ &ДатаНачала И &ДатаКонца

Получение начала других периодов и смещение дат

В качестве второго параметра функции НАЧАЛОПЕРИОДА можно указывать не только ДЕНЬ, но и другие типы периодов: СЕКУНДА, МИНУТА, ЧАС, НЕДЕЛЯ, ДЕКАДА, МЕСЯЦ, КВАРТАЛ, ПОЛУГОДИЕ, ГОД.

Если необходимо получить начало дня со сдвигом на определенное количество суток (например, начало следующего дня), сочетаем НАЧАЛОПЕРИОДА с функцией ДОБАВИТЬКДАТЕ:

ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(ИсходнаяДата, ДЕНЬ), ДЕНЬ, 1)

← На главную