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