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