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

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

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

Использование литералов даты и времени

В отличие от классического SQL, где даты могут записываться в разных форматах (например, через решетки или кавычки), в языке запросов 1С существует строго определенная конструкция — ДАТАВРЕМЯ. Она позволяет жестко зашить конкретный момент времени прямо в текст запроса. Рассмотрим синтаксис этой конструкции:

ДАТАВРЕМЯ(Год, Месяц, День, Час, Минута, Секунда)

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

  1. Полная дата со временем: если нам нужно выбрать данные за конкретную секунду. ГДЕ Продажи.Период = ДАТАВРЕМЯ(2023, 10, 25, 14, 30, 0)
  2. Дата без указания времени: если время не указано, система автоматически подставит начало дня (00:00:00).
    
    ГДЕ Продажи.Период >= ДАТАВРЕМЯ(2023, 10, 25) 
    // Это эквивалентно 25.10.2023 00:00:00
    
  3. Пустая дата: в 1С пустая дата — это начало первого года. Это часто используется для проверки незаполненных полей. ГДЕ Документ.ДатаОплаты = ДАТАВРЕМЯ(1, 1, 1)

Вычисление временных интервалов: функция ДОБАВИТЬКДАТЕ

Один из частых вопросов: как задать интервал вида «3 минуты назад»? В языке запросов 1С нет функции NOW(), но есть мощный инструмент ДОБАВИТЬКДАТЕ. Эта функция позволяет прибавлять или отнимать определенное количество временных единиц (секунд, минут, дней и т.д.) от заданной даты.

Синтаксис функции: ДОБАВИТЬКДАТЕ(ИсходнаяДата, ТипПериода, Количество).

Рассмотрим ситуацию, когда нам нужно найти записи за последние 3 минуты относительно какой-то даты. Чтобы «отнять» время, мы просто используем отрицательное число в параметре количества. Посмотрим на пример кода:


ВЫБРАТЬ
    События.Наименование,
    События.Период
ИЗ
    РегистрСведений.События КАК События
ГДЕ
    События.Период МЕЖДУ ДОБАВИТЬКДАТЕ(&ТекущийМомент, МИНУТА, -3) И &ТекущийМомент

Здесь мы используем параметр &ТекущийМомент. Важно помнить, что внутри самого текста запроса получить текущее системное время невозможно. Это сделано для обеспечения стабильности выполнения запроса на стороне СУБД.

Проблема отсутствия «Текущей даты» в запросе

Разберем важный нюанс: почему в запросе 1С нет функции типа ТекущаяДата()? Это архитектурное ограничение. Если бы такая функция существовала, результат одного и того же запроса мог бы различаться в зависимости от миллисекунды его запуска, что затрудняет кэширование и оптимизацию планов запросов СУБД.

Правильный подход: всегда передавайте текущую дату как параметр перед выполнением запроса.


Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ * ИЗ Справочник.Номенклатура ГДЕ ДатаСоздания > &ТекДата";
Запрос.УстановитьПараметр("ТекДата", ТекущаяДата());
Результат = Запрос.Выполнить();

Функции НАЧАЛОПЕРИОДА и КОНЕЦПЕРИОДА

Когда мы работаем с интервалами, нам часто нужно «округлить» дату до начала дня, месяца или года. Для этого используются функции НАЧАЛОПЕРИОДА и КОНЕЦПЕРИОДА. Это гораздо эффективнее, чем пытаться манипулировать строками или числами.

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

ГДЕ Продажи.Период >= НАЧАЛОПЕРИОДА(&ПараметрДата, ДЕНЬ)

Функция КОНЕЦПЕРИОДА работает аналогично, но устанавливает время на последнюю секунду указанного периода (например, 23:59:59 для дня).

Вычисление разницы между двумя датами

Если задача стоит не в фильтрации, а в расчете длительности (например, сколько минут прошло между заказом и отгрузкой), мы используем функцию РАЗНОСТЬДАТ.

Синтаксис: РАЗНОСТЬДАТ(Дата1, Дата2, ТипПериода).

Важное замечание: функция считает количество границ периодов. Это означает, что разница в днях между «сегодня 23:59:59» и «завтра 00:00:01» будет равна 1, хотя фактически прошло всего 2 секунды. Это нужно учитывать при расчетах высокой точности.

Оптимизация: SARGability запросов

Проанализируем ситуацию с точки зрения производительности. Когда мы пишем условие ГДЕ, важно, чтобы СУБД могла использовать индексы. Если вы примените функцию к полю таблицы, индекс может «перестать работать».

Как делать не стоит (медленно): ГДЕ ДОБАВИТЬКДАТЕ(ДатаДокумента, ДЕНЬ, 1) > &НужнаяДата Здесь СУБД придется вычислить функцию для каждой строки таблицы, прежде чем сравнить ее.

Как делать правильно (быстро): ГДЕ ДатаДокумента > ДОБАВИТЬКДАТЕ(&НужнаяДата, ДЕНЬ, -1) Здесь функция вычисляется один раз (для параметра), а затем СУБД быстро находит нужные строки по индексу поля ДатаДокумента.

Работа с Границей и Моментом Времени

В контексте виртуальных таблиц (например, остатков или оборотов) часто недостаточно просто даты. Если в одну и ту же секунду введено несколько документов, порядок их следования определяется ссылкой. Для корректного получения итогов используются объекты Граница и МоментВремени.

Хотя эти объекты нельзя создать внутри текста запроса (через ДАТАВРЕМЯ), их крайне важно передавать в параметры, если вам нужны остатки включая или исключая движения конкретного документа.


// Пример передачи границы в параметр запроса
Граница = Новый Граница(ДокументСсылка.МоментВремени(), ВидГраницы.Включая);
Запрос.УстановитьПараметр("ПериодГраница", Граница);

Итоги

Мы рассмотрели основные способы работы с временными данными в 1С. Подведем итог:

Эти правила позволят вам писать эффективные и надежные запросы для любых задач автоматизации.

← На главную