Разработка и Конфигурация · 11 мин
Как явно указать дату в запросе 1С
Как явно указать дату в запросе 1С: литерал ДАТАВРЕМЯ, передача параметра типа Дата, границы периода, типичные ошибки и проверка результата.
Явное указание даты в запросе 1С нужно в трёх типовых ситуациях: когда требуется константная дата прямо в тексте запроса, когда дата приходит из кода как параметр и когда необходимо задать границу периода с точностью до секунды или до конца дня. Во всех трёх случаях синтаксис разный, и путаница между ними — самая частая причина пустых выборок и ошибок компиляции запроса.
Язык запросов 1С не понимает строку вида "01.01.2026" как дату. Если передать дату строкой без преобразования, запрос либо не выполнится, либо сравнение пройдёт как сравнение строк, и результат будет непредсказуемым. Поэтому дату всегда задают либо литералом ДАТАВРЕМЯ, либо параметром с типом Дата, либо объектом Граница для виртуальных таблиц.
Ниже разобраны все способы с примерами кода, правила выбора между ними, проверка результата и типичные ошибки, из-за которых отбор по дате «не срабатывает».
Литерал ДАТАВРЕМЯ: дата прямо в тексте запроса
Единственный способ записать конкретную дату непосредственно в тексте запроса — функция-литерал ДАТАВРЕМЯ. Она принимает числовые аргументы: год, месяц, день и необязательно час, минуту, секунду. Минимальная форма — три параметра, тогда время будет равно 00:00:00.
ВЫБРАТЬ
Продажи.Номенклатура,
Продажи.Количество
ИЗ
Документ.РеализацияТоваровУслуг КАК Продажи
ГДЕ
Продажи.Дата >= ДАТАВРЕМЯ(2026, 1, 1, 0, 0, 0)
И Продажи.Дата <= ДАТАВРЕМЯ(2026, 1, 31, 23, 59, 59)
Обратите внимание на формат: год указывается четырьмя цифрами, месяц и день — числами без кавычек и без ведущего нуля (допустимо и с нулём: 01). Кавычки вокруг аргументов недопустимы — ДАТАВРЕМЯ("2026", "01", "01") вызовет ошибку компиляции запроса.
Литерал уместен, когда дата действительно постоянна: например, в плане обмена, в отборе архивных данных или в служебном запросе с фиксированной точкой отсчёта. Если дата может измениться хотя бы при следующем запуске — используйте параметр, иначе придётся править модуль вместо настройки.
Передача даты параметром из кода
Параметр — основной способ, когда дата вычисляется в коде: начало месяца, выбранная пользователем дата, текущая дата сеанса. В тексте запроса параметр обозначается амперсандом, значение присваивается методом УстановитьПараметр.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Товары.Номенклатура
|ИЗ
| Документ.РеализацияТоваровУслуг КАК Товары
|ГДЕ
| Товары.Дата МЕЖДУ &НачалоПериода И &КонецПериода";
Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(ДатаНачала));
Запрос.УстановитьПараметр("КонецПериода", КонецДня(ДатаОкончания));
Результат = Запрос.Выполнить();
Ключевая пара функций — НачалоДня() и КонецДня(). КонецДня возвращает 23:59:59, и без неё отбор «по дату включительно» потеряет все документы, проведённые в течение последнего дня после полуночи. Это самая распространённая ошибка при периодических выборках.
Тип параметра определяется значением: если передать значение типа Дата, сравнение в запросе будет корректным. Если передать строку — запрос либо упадёт с ошибкой несоответствия типов, либо (в сравнениях со строковыми представлениями) отработает не так, как ожидалось. Убедиться в типе можно через ТипЗнч(Значение) = Тип("Дата") до установки параметра.
Граница периода для виртуальных таблиц регистров
У документов дата не уникальна: несколько документов могут иметь одинаковые дату и время. Поэтому для виртуальных таблиц регистров (Остатки, Обороты, ОстаткиИОбороты) отбор по параметру «Период» с обычной датой может включить или исключить движения документа, стоящего ровно на границе, непредсказуемым образом.
Решение — объект Граница. Он строится из момента времени (или из даты) и вида границы: Включая или Исключая. Для остатков на начало дня, когда движения первого документа дня учитывать не нужно, границу задают как Исключая.
ГраницаОстатков = Новый Граница(
НачалоДня(ДатаОтчета),
ВидГраницы.Исключая);
Запрос.УстановитьПараметр("ГраницаОстатков", ГраницаОстатков);
// В тексте запроса:
// РегистрНакопления.ТоварыНаСкладах.Остатки(&ГраницаОстатков, )
Если вместо границы передать просто НачалоДня(Дата), остатки будут рассчитаны с учётом движений документов, проведённых ровно в 00:00:00, — для документов с непустым временем это обычно не критично, но для документов, установленных на начало дня, даст расхождение с отчётом, построенным через СКД с корректной границей.
Сравнение вариантов
Подходит для фиксированной даты в тексте запроса. Ограничение: любое изменение даты требует правки кода.
Универсальный способ для дат из кода и пользовательского ввода. Требует корректного типа значения и КонецДня для верхней границы.
Обязателен для точных отборов по виртуальным таблицам регистров, когда на границе периода стоят документы. Избыточен для отборов по реквизиту Дата обычных таблиц.
Дата в параметрах виртуальных таблиц и конструкции МЕЖДУ
У виртуальных таблиц Обороты и ОстаткиИОбороты период задаётся двумя параметрами: начало и конец. Оба принимают либо дату, либо границу. Порядок параметров фиксирован, пропускать нельзя — если период не нужен, ставят запятую без значения или вообще не открывают скобки параметров.
ВЫБРАТЬ
Обороты.Номенклатура,
Обороты.КоличествоОборот
ИЗ
РегистрНакопления.Продажи.Обороты(
&НачалоПериода,
&КонецПериода,
День,
) КАК Обороты
В условиях по обычным таблицам удобна конструкция МЕЖДУ — она включает обе границы. Но помните: МЕЖДУ &Начало И &Конец с параметром Конец = ДатаОкончания (без КонецДня) снова обрежет последний день. Альтернатива — полуоткрытый интервал: Дата >= &Начало И Дата < &СледующийДень, где СледующийДень = КонецДня(ДатаОкончания) + 1. Такой вариант не зависит от точности хранения секунд и надёжнее при миграциях между СУБД.
- 1Определите, откуда приходит дата: константа, пользовательский ввод, вычисление в коде.
- 2Для константы напишите литерал ДАТАВРЕМЯ(год, месяц, день, часы, минуты, секунды) прямо в тексте запроса.
- 3Для значения из кода добавьте параметр &ИмяПараметра и установите его методом УстановитьПараметр значением типа Дата.
- 4Нижнюю границу оберните в НачалоДня(), верхнюю — в КонецДня() или используйте полуоткрытый интервал.
- 5Для виртуальных таблиц регистров замените дату на объект Граница с нужным видом (Включая/Исключая).
- 6Выполните запрос в консоли запросов и сверьте количество строк и граничные документы с ожиданием.
Проверка результата и отладка
Проверять отбор по дате удобнее всего в консоли запросов: установите те же параметры, что и в коде, и посмотрите, попадает ли контрольный документ на границе периода в выборку. Если документ «на границе» теряется — причина почти всегда в секундах (нет КонецДня) или в том, что виртуальной таблице передана дата вместо границы.
Второй приём — временно вывести в запрос само значение параметра: ВЫБРАТЬ &НачалоПериода, &КонецПериода. Так видно, что реально пришло в запрос: тип, время, пустая ли дата. Это быстрее, чем искать ошибку в логике запроса.
Третья контрольная точка — сверка с типовым отчётом. Если ваш запрос по оборотам даёт сумму, отличную от стандартного отчёта за тот же период, сравните границы: типовые отчёты используют границы с видом Исключая для начала и включение конца периода.
Как проверить результат
Присутствует в выборке
Отсутствует — проверьте, не передана ли граница Включая там, где нужно Исключая, и наоборот
Присутствует в выборке
Отсутствует — верхняя граница задана без КонецДня
Тип Дата, ожидаемое время
Строка или пустая дата — ошибка при установке параметра
Совпадает
Расходится — неверные границы виртуальной таблицы
Особые случаи: текущая дата, часовые пояса, компоновка данных
Для «сегодня» на сервере используйте ТекущаяДатаСеанса(), а не ТекущаяДата() — последняя на сервере возвращает время сервера, что в распределённой инфраструктуре может отличаться от времени пользователя. В тексте самого запроса функции текущей даты нет — её всегда передают параметром.
В схеме компоновки данных даты периода обычно приходят как параметры НачалоПериода и КонецПериода типа Дата. В настройках отчёта пользователь задаёт стандартный период, а СКД сама подставляет значения; вручную вызывать КонецДня в этом случае не нужно — СКД корректно заполняет конец периода значением 23:59:59, если параметр объявлен как Дата с составом «Дата и время».
Если дата хранится в базе в часовом поясе, отличном от пояса пользователя (например, UTC в регистрах обмена), приводите её к поясу сеанса до передачи в запрос — в языке запросов нет встроенных средств пересчёта часовых поясов.
Часто задаваемые вопросы
Как задать в запросе пустую дату?
Литералом ДАТАВРЕМЯ(1, 1, 1). Проверка реквизита на пустую дату выглядит так: ГДЕ Документ.ДатаОплаты = ДАТАВРЕМЯ(1, 1, 1). Сравнение с NULL или пустой строкой для этого не подходит.
Почему ДАТАВРЕМЯ(2026, 1, 32) или неверный месяц вызывает ошибку?
Литерал проверяется на корректность календарной даты при компиляции запроса. Несуществующая комбинация (32 день, 13 месяц, 29 февраля невисокосного года) даёт ошибку ещё до выполнения, что удобно для раннего обнаружения опечаток.
Можно ли передать в параметр только дату без времени?
Тип Дата в 1С всегда содержит время. «Дата без времени» — это дата со временем 00:00:00, которое даёт НачалоДня(). Физически отсечь время нельзя, можно только нормализовать его функциями НачалоДня/КонецДня.
Чем отличается передача даты и границы в виртуальную таблицу Остатки?
Дата задаёт точку расчёта остатков с точностью до секунды, без привязки к конкретному документу. Граница строится от момента времени документа и позволяет явно указать, включать ли движения этого документа в расчёт — это важно, когда на границе периода стоит документ.
Как сравнить в запросе только даты, игнорируя время?
Используйте функции языка запросов: НАЧАЛОПЕРИОДА(Дата, ДЕНЬ) приводит значение к началу дня, и сравнение идёт уже без учёта времени. Например: ГДЕ НАЧАЛОПЕРИОДА(Док.Дата, ДЕНЬ) = НАЧАЛОПЕРИОДА(&Дата, ДЕНЬ). Учтите, что такое условие не использует индекс по полю Дата и на больших таблицах работает медленнее, чем диапазон от НачалоДня до КонецДня.
Почему запрос с параметром-датой работает в консоли, но не в коде?
Чаще всего в коде параметр установлен значением другого типа (строка, число) или не установлен вовсе — тогда запрос падает с ошибкой «Параметр не найден». Выведите значение через ВЫБРАТЬ &Параметр и проверьте тип через ТипЗнч до установки.
Что важно запомнить
Константную дату пишите литералом ДАТАВРЕМЯ, дату из кода передавайте параметром типа Дата с НачалоДня/КонецДня, а для виртуальных таблиц регистров используйте объект Граница. Проверяйте граничные документы и типы параметров — большинство ошибок отбора по дате связано с секундами и неверным типом значения.