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