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

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

В процессе разработки на платформе 1С:Предприятие 8 программисты часто сталкиваются с необходимостью фильтрации данных по текущему моменту времени прямо в тексте запроса. Типичный пример — выборка просроченных задач или документов, дата которых больше текущей. Однако попытка написать в консоли запросов или коде конструкцию вида ГДЕ Дата > ТекущаяДата приводит к ошибке, так как язык запросов 1С не содержит встроенной функции получения системного времени. В этой статье мы подробно разберем, почему это так, и рассмотрим все доступные способы решения этой задачи — от стандартных до продвинутых.

Способ 1. Использование параметров запроса (Классический подход)

Рассмотрим самый правильный и производительный метод — использование параметров. Платформа 1С намеренно разделяет подготовку текста запроса и передачу в него динамических данных. Это позволяет системе управления базами данных (СУБД) эффективно кэшировать планы выполнения запросов.

Проанализируем ситуацию: если бы функция ГЕТДАТА() (аналог SQL GETDATE()) существовала в языке запросов, SQL-серверу было бы сложнее строить оптимальный план, так как значение менялось бы каждую миллисекунду. Использование параметра &ТекДата позволяет системе один раз построить план и переиспользовать его.

Для реализации этого метода в коде выполним следующие шаги:

  1. В тексте запроса укажем параметр через символ амперсанда.
  2. В коде на встроенном языке установим значение этого параметра.

Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ПоступлениеТоваровУслугТовары.Ссылка КАК Ссылка
    |ИЗ
    |	Документ.ПоступлениеТоваровУслуг.Товары КАК ПоступлениеТоваровУслугТовары
    |ГДЕ
    |	ПоступлениеТоваровУслугТовары.Ссылка.Дата > &ТекущаяДата";

// Установка параметра
Запрос.УстановитьПараметр("ТекущаяДата", ТекущаяДата());

РезультатЗапроса = Запрос.Выполнить();

Способ 2. Текущая дата в системе компоновки данных (СКД)

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

Посмотрим на вкладку «Параметры» в конструкторе СКД. Для параметра с именем ТекДата мы можем настроить поле «Выражение». Здесь доступны функции встроенного языка. Рассмотрим два варианта заполнения:

  1. Прямое использование функции: Просто напишем в выражении ТекущаяДата() или ТекущаяДатаСеанса(). Платформа сама вычислит значение в момент инициализации отчета.
  2. Использование общего модуля: Если требуется сложная логика (например, начало текущего дня или смещение на 3 часа), создадим в общем модуле (с установленной галкой «Сервер» и «Вызов сервера») экспортную функцию.

Пример кода в общем модуле РаботаСДатамиПолныйДоступ:


Функция ПолучитьНачалоТекущегоДня() Экспорт
    Возврат НачалоДня(ТекущаяДатаСеанса());
КонецФункции

В СКД в поле «Выражение» для параметра укажем: РаботаСДатамиПолныйДоступ.ПолучитьНачалоТекущегоДня(). Это гарантирует, что отчет всегда будет открываться с актуальной датой без вмешательства пользователя.

Способ 3. Особенности работы с Динамическими списками

При работе с управляемыми формами часто требуется фильтровать данные в динамических списках (например, скрывать будущие задачи). Выясним причину, по которой обычный параметр может не подойти: динамический список не обновляется «сам по себе» при наступлении следующей секунды. Если вы установили параметр при открытии формы, он останется статичным.

Для решения этой проблемы проанализируем два подхода:

  1. Обработчик ожидания: Можно использовать метод ПодключитьОбработчикОжидания, который раз в минуту будет обновлять параметр &ТекущаяДата в компоновщике настроек динамического списка.
  2. Параметры сеанса: Это более продвинутый метод. Вместо обращения к константам (которые создают лишние блокировки в базе данных при частом обновлении), мы можем использовать ПараметрыСеанса. Они хранятся в памяти сервера для каждого пользователя индивидуально.

Однако помните: использование параметров сеанса непосредственно в тексте запроса динамического списка возможно, но это требует их предварительной инициализации в модуле сеанса. Это избавляет от «грязного» кода и позволяет избежать использования констант, которые влияют на всех пользователей сразу.

Способ 4. Вычисление даты в строке запроса (Метод "Костыль")

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

Рассмотрим пример формирования такой строки:


ТекДата = ТекущаяДата();
ТекстЗапроса = "ГДЕ Документ.Дата > ДАТАВРЕМЯ(" 
    + Формат(Год(ТекДата), "ЧГ=0") + "," 
    + Месяц(ТекДата) + "," 
    + День(ТекДата) + "," 
    + Час(ТекДата) + "," 
    + Минута(ТекДата) + "," 
    + Секунда(ТекДата) + ")";

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

Способ 5. Оптимизация: Текущая дата в виртуальных таблицах

Проанализируем крайне важный нюанс производительности. Если ваш запрос обращается к виртуальным таблицам (например, РегистрНакопления.ОстаткиИОбороты), никогда не используйте условие по текущей дате в секции ГДЕ.

Сравним два подхода:

Пример правильного запроса:


ВЫБРАТЬ
    Продажи.СуммаОборот
ИЗ
    РегистрНакопления.Продажи.Обороты(, &КонецПериода, , ) КАК Продажи

В данном случае СУБД сразу отсечет ненужные записи на уровне обращения к индексам, что обеспечит максимальную скорость работы.

Важные различия: ТекущаяДата() vs ТекущаяДатаСеанса()

В завершение разберем критическую деталь, которую часто упускают. В системе 1С существует два основных понятия времени:

  1. ТекущаяДата() — возвращает время сервера, на котором выполняется код.
  2. ТекущаяДатаСеанса() — учитывает часовой пояс пользователя, заданный в настройках сеанса.

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

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

← На главную