Разработка и Конфигурация · 9 мин
Как указать текущую дату в запросе 1С
Как указать текущую дату в запросе 1С: функция ТекущаяДатаСеанса, передача параметра, сравнение дат, типичные ошибки и примеры кода для разработчика.
Задача подставить текущую дату в запрос возникает постоянно: нужно выбрать документы за сегодня, отобрать актуальные цены, проверить просроченные задачи или построить отчёт «на сейчас». В языке запросов 1С для этого есть встроенный механизм, но у него есть тонкости, из-за которых запросы нередко возвращают не то, что ожидал разработчик.
Главная тонкость — разница между датой сервера, датой клиента и датой сеанса. В файловой базе на одном компьютере они обычно совпадают, а в клиент-серверном режиме или при работе пользователей из разных часовых поясов — могут различаться. Поэтому важно не просто «вставить дату», а понимать, откуда она берётся и в каком виде попадает в сравнение.
Ниже разобраны оба рабочих способа — функция ТекущаяДатаСеанса() в тексте запроса и передача даты параметром, а также сравнение дат без времени, работа в СКД и типичные ошибки, которые приводят к пустым или неверным выборкам.
Способ 1: функция ТекущаяДатаСеанса() прямо в тексте запроса
Язык запросов 1С поддерживает функцию ТекущаяДатаСеанса() — она вычисляется на сервере в момент выполнения запроса и возвращает дату и время текущего сеанса с учётом часового пояса сеанса. Это самый короткий способ, не требующий передачи параметров.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЗаказКлиента.Ссылка КАК Заказ,
| ЗаказКлиента.Дата КАК Дата
|ИЗ
| Документ.ЗаказКлиента КАК ЗаказКлиента
|ГДЕ
| ЗаказКлиента.ДатаОтгрузки < &ТекущаяДата";
Однако функцию внутри текста используют так — без параметра вообще:
Запрос.Текст =
"ВЫБРАТЬ
| Задача.Ссылка КАК Задача
|ИЗ
| Задача.ЗадачаИсполнителя КАК Задача
|ГДЕ
| Задача.СрокИсполнения < ТекущаяДатаСеанса()";
Функция вызывается без аргументов, скобки обязательны. Результат — значение типа Дата с точностью до секунды. Если поле в базе хранит дату с временем (а документы 1С хранят именно так), сравнение идёт с точностью до секунды, и это нужно учитывать при отборе «за сегодня».
Способ 2: передать дату через параметр запроса
Второй подход — вычислить дату в коде и передать её в запрос параметром. Это даёт полный контроль над значением: можно отсечь время, сдвинуть дату на начало дня или на нужное количество дней назад.
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("ТекущаяДата", ТекущаяДатаСеанса());
Запрос.Текст =
"ВЫБРАТЬ
| Платеж.Ссылка КАК Платеж
|ИЗ
| Документ.ПоступлениеОплаты КАК Платеж
|ГДЕ
| Платеж.Дата <= &ТекущаяДата";
Результат = Запрос.Выполнить();
Если нужно сравнивать только день без времени, дату приводят к началу дня до передачи в запрос:
Запрос.УстановитьПараметр("НачалоСегодня", НачалоДня(ТекущаяДатаСеанса()));
Запрос.УстановитьПараметр("КонецСегодня", КонецДня(ТекущаяДатаСеанса()));
Параметр предпочтительнее, когда одна и та же дата используется в нескольких местах запроса или в пакете запросов: значение фиксируется один раз, и все части пакета работают с одинаковым моментом времени. С функцией ТекущаяДатаСеанса() каждый запрос пакета теоретически может получить значение, отличающееся на секунды.
Сравнение вариантов
Коротко, не нужен параметр. Подходит для простых разовых отборов. Нельзя заранее отсечь время.
Полный контроль: можно передать начало дня, конец дня, произвольный сдвиг. Обязателен, когда одно значение нужно в нескольких запросах.
Для отчётов и динамических списков: пользователь сам управляет датой, по умолчанию подставляется текущая.
Как сравнить даты без учёта времени
Документ в 1С хранит дату с точностью до секунды, поэтому условие Документ.Дата = &ТекущаяДата почти никогда не сработает: совпадение до секунды практически невозможно. Для отбора «за сегодня» используют диапазон или приведение к периоду.
Первый вариант — диапазон от начала до конца дня:
"ГДЕ
| Документ.Дата МЕЖДУ &НачалоСегодня И &КонецСегодня"
Второй вариант — функция языка запросов НАЧАЛОПЕРИОДА, которая усекает дату до указанного периода:
"ГДЕ
| НАЧАЛОПЕРИОДА(Документ.Дата, ДЕНЬ) = НАЧАЛОПЕРИОДА(&ТекущаяДата, ДЕНЬ)"
У второго варианта есть цена: функция применяется к полю таблицы, и индекс по дате при таком условии не используется, что на больших таблицах заметно замедляет запрос. Для массовых отборов предпочтителен диапазон МЕЖДУ по индексированному полю.
Текущая дата в СКД и динамических списках
В отчётах на системе компоновки данных и в динамических списках жёстко зашивать ТекущаяДатаСеанса() в текст запроса не принято. Вместо этого добавляют параметр с типом СтандартнаяДатаНачала — тогда пользователь отчёта может сам выбрать дату, а по умолчанию подставляется текущая.
Порядок настройки в схеме компоновки: на закладке «Параметры» добавьте параметр, например Период, установите ему тип значения «Стандартная дата начала». В тексте запроса используйте его обычным образом: ГДЕ Документ.Дата <= &Период. При необходимости внутри выражений СКД доступна функция ТекущаяДатаСеанса() и выражение &ТекущаяДата через вычисляемые поля.
Для динамических списков (например, список просроченных задач на рабочем столе) параметр устанавливают программно при создании формы:
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Список.Параметры.УстановитьЗначениеПараметра("ТекущаяДата", ТекущаяДатаСеанса());
КонецПроцедуры
- 1Определите, где выполняется запрос: простой запрос, СКД или динамический список.
- 2Для простого запроса вычислите НачалоДня(ТекущаяДатаСеанса()) и КонецДня(ТекущаяДатаСеанса()) и передайте оба параметра.
- 3В тексте запроса используйте условие Дата МЕЖДУ &НачалоСегодня И &КонецСегодня.
- 4Выполните запрос и проверьте, что в выборку попали документы за текущий день и не попали вчерашние.
- 5Для СКД замените параметры на СтандартнаяДатаНачала, чтобы пользователь мог менять дату без доработки кода.
Часовые пояса и дата сеанса
ТекущаяДатаСеанса() возвращает время сервера, приведённое к часовому поясу сеанса пользователя. Если база работает в клиент-серверном режиме и пользователи сидят в разных регионах, «сегодня» для двух пользователей может быть разным календарным днём. Это нормальное поведение, но его нужно учитывать в регламентных заданиях: у фонового задания нет пользовательского сеанса, и дата берётся по часовому поясу сервера или информационной базы.
Если учёт ведётся строго по одному часовому поясу (например, головной офис), в регламентных операциях дату лучше вычислять явно относительно заданного пояса, а не полагаться на дату сеанса фонового задания. Иначе документы, созданные около полуночи, могут попадать не в тот отчётный день.
Проверка результата и отладка
Быстрее всего проверить отбор по текущей дате в консоли запросов: задайте параметр вручную, выполните запрос и посмотрите, какие записи попали в выборку. Затем замените параметр на ТекущаяДатаСеанса() и сравните результат — он должен совпадать с точностью до момента выполнения.
Если выборка пустая, проверьте три вещи: тип параметра (должна быть Дата, а не Строка), наличие времени в сравниваемых значениях и часовой пояс сеанса. Чаще всего «запрос не работает» означает, что дата документа содержит время, а условие построено на точное равенство.
Как проверить результат
Дата (с временем или без)
Строка — сравнение идёт посимвольно
Есть все документы текущего дня
Пусто или попадают чужие дни — ошибка в границах диапазона
Запрос отрабатывает быстро, условие по индексированному полю
Заметная задержка — вероятно, НАЧАЛОПЕРИОДА в условии по полю
Что важно запомнить
В запросе 1С текущую дату получают функцией ТекущаяДатаСеанса() или передают параметром. Для отбора «за сегодня» используйте диапазон от начала до конца дня, а не равенство. В СКД и динамических списках применяйте параметр типа СтандартнаяДатаНачала, а в серверном коде — только ТекущаяДатаСеанса(), никогда ТекущаяДата().
Частые вопросы
Чем ТекущаяДатаСеанса() отличается от ТекущаяДата()?
ТекущаяДатаСеанса() возвращает время сервера, приведённое к часовому поясу сеанса, и работает везде, включая серверный код. ТекущаяДата() возвращает время клиентского компьютера и доступна только на клиенте. В запросах и серверных процедурах используйте только ТекущаяДатаСеанса().
Почему условие Дата = &ТекущаяДата ничего не находит?
Даты документов хранятся с точностью до секунды, и совпадение с моментом выполнения запроса практически невозможно. Замените равенство на диапазон: Дата МЕЖДУ НачалоДня(дата) И КонецДня(дата).
Можно ли в запросе вычесть дни из текущей даты?
Да, есть функции ДОБАВИТЬКДАТЕ и РАЗНОСТЬДАТ. Например, неделю назад: ДОБАВИТЬКДАТЕ(ТекущаяДатаСеанса(), ДЕНЬ, -7). Альтернатива — вычислить дату в коде и передать параметром.
Как задать текущую дату в отчёте на СКД, чтобы пользователь мог её менять?
Добавьте в схеме компоновки параметр с типом «Стандартная дата начала» и используйте его в тексте запроса. По умолчанию подставится текущая дата, а пользователь сможет выбрать другую в настройках отчёта.
Работает ли ТекущаяДатаСеанса() в регламентных заданиях?
Работает, но возвращает время по часовому поясу сервера или информационной базы, так как пользовательского сеанса у фонового задания нет. Если учёт привязан к конкретному региону, вычисляйте дату явно относительно нужного часового пояса.