Работа с датами в запросах 1С:Предприятие — одна из самых востребованных задач при разработке отчетов, обработок и интеграционных решений. Даже простая выборка документов за период может превратиться в головоломку, если не знать нюансов синтаксиса и особенностей преобразования типов. В этой статье мы разберем все способы выражения дат в запросах: от базовых конструкций ДАТАВРЕМЯ() до сложных условий с использованием виртуальных таблиц и временных функций.

Особое внимание уделим типичным ошибкам, которые приводят к некорректным результатам или падению производительности. Например, почему МЕЖДУ может пропустить крайние даты, как правильно сравнивать даты с временем, и почему нельзя слепо копировать SQL-синтаксис в 1С-запросы. Материал будет полезен как начинающим разработчикам, так и опытным специалистам, которые хотят оптимизировать свои запросы.

1. Базовый синтаксис дат в запросах 1С

В языке запросов даты можно выражать несколькими способами, каждый из которых имеет свои особенности. Основной инструмент — функция ДАТАВРЕМЯ(), которая создает значение типа Дата из отдельных компонентов (год, месяц, день) или из строки.

Примеры базового использования:

  • 📅 ДАТАВРЕМЯ(2026, 5, 15) — создаст дату 15 мая 2026 года без времени
  • ДАТАВРЕМЯ(2026, 5, 15, 14, 30, 0) — та же дата, но с временем 14:30:00
  • 📝 ДАТАВРЕМЯ("20260515") — альтернативный строковый формат (YYYYMMDD)

Например, ДАТАВРЕМЯ("15.05.2026") вызовет ошибку — сначала строку нужно привести к корректному формату с помощью ФОРМАТ() или других функций.

📊 Какой формат дат вы используете чаще в запросах 1С?
Числовые параметры (год, месяц, день)
Строковый формат YYYYMMDD
Функции ТЕКУЩАЯДАТА()/НАЧАЛОПЕРИОДА()
Другое

2. Работа с текущей датой и относительными периодами

Для динамических запросов, где нужно оперировать текущей датой или относительными периодами (например, "за последний месяц"), используются специальные функции:

ФункцияОписаниеПример результата (на 15.05.2026)
ТЕКУЩАЯДАТА()Возвращает текущую дату и время на сервере15.05.2026 14:30:00
НАЧАЛОПЕРИОДА()Возвращает начало периода (день, месяц, квартал, год)НАЧАЛОПЕРИОДА(ТЕКУЩАЯДАТА(), "МЕСЯЦ") → 01.05.2026 00:00:00
КОНЕЦПЕРИОДА()Возвращает конец периодаКОНЕЦПЕРИОДА(ТЕКУЩАЯДАТА(), "ДЕНЬ") → 15.05.2026 23:59:59
ДОБАВИТЬМЕСЯЦ()Сдвигает дату на указанное количество месяцевДОБАВИТЬМЕСЯЦ(ТЕКУЩАЯДАТА(), -1) → 15.04.2026

Эти функции особенно полезны в отчетах, где период формируется динамически. Например, чтобы получить документы за текущий месяц, можно написать:

ВЫБРАТЬ

Документ.Ссылка КАК Ссылка

ИЗ

Документ.ЗаказПокупателя КАК Документ

ГДЕ

Документ.Дата МЕЖДУ НАЧАЛОПЕРИОДА(ТЕКУЩАЯДАТА(), "МЕСЯЦ")

И КОНЕЦПЕРИОДА(ТЕКУЩАЯДАТА(), "МЕСЯЦ")

⚠️ Внимание: Функция ТЕКУЩАЯДАТА() возвращает дату и время на сервере 1С, а не на клиентском компьютере. Если сервер и клиент находятся в разных часовых поясах, это может привести к неожиданным результатам. Всегда проверяйте настройки часового пояса в кластере серверов.

3. Сравнение дат и интервалы: МЕЖДУ vs отдельные условия

Один из самых распространенных вопросов — как правильно задать интервал дат в запросе. На первый взгляд, конструкция МЕЖДУ кажется удобной:

ГДЕ

Документ.Дата МЕЖДУ &НачалоПериода И &КонецПериода

Однако у этого подхода есть критическая особенность: оператор МЕЖДУ включает обе границы интервала, но только если время в датах равно 00:00:00. Если в &КонецПериода указано время (например, 23:59:59), то документы с этой датой не попадут в выборку!

Безопасная альтернатива — использовать два отдельных условия:

ГДЕ

Документ.Дата >= &НачалоПериода

И Документ.Дата < ДОБАВИТЬКДАТЕ(&КонецПериода, СЕКУНДА, 1)

  • Плюсы: работает корректно с любым временем в границах
  • Минусы: менее читаемый код, особенно при вложенных условиях
ГДЕ Документ.Дата >= ДАТАВРЕМЯ(2026, 5, 15)

И Документ.Дата < ДАТАВРЕМЯ(2026, 5, 16)

Это гарантированно включит все документы за 15 мая, независимо от времени их проведения.-->

4. Преобразование строк в даты и обратно

Часто данные о датах хранятся в строковом формате (например, в файлах обмена или внешних источниках). Чтобы использовать их в запросах, нужно правильно преобразовать строки в тип Дата. Для этого служат функции ВЫРАЗИТЬ() и ФОРМАТ().

Пример преобразования строки формата "DD.MM.YYYY":

ВЫБРАТЬ

ВЫРАЗИТЬ(ФОРМАТ("15.05.2026", "ДФ=yyyyMMdd") КАК ДАТА) КАК ПреобразованнаяДата

Обратное преобразование (дата в строку) выполняется с помощью ФОРМАТ() или ПРЕДСТАВИТЬ():

ВЫБРАТЬ

ФОРМАТ(Документ.Дата, "ДФ=dd.MM.yyyy") КАК ДатаСтрокой

⚠️ Внимание: При обмене данными с внешними системами (например, через REST API или JSON) даты часто передаются в формате ISO 8601 (например, "2026-05-15T14:30:00"). Для корректного преобразования таких строк используйте комбинацию СТРЗАМЕНИТЬ() и ФОРМАТ(), чтобы привести строку к формату YYYYMMDDHHMMSS.
Что будет если передать некорректную строку в ВЫРАЗИТЬ?

Если строка не соответствует ожидаемому формату даты (например, "32.01.2026" или "abc"), функция ВЫРАЗИТЬ() вернет NULL, а не вызовет ошибку. Это может привести к скрытым багам, если не проверять результат на пустое значение.

5. Работа с виртуальными таблицами и датами

Виртуальные таблицы (например, Документ.ЗаказПокупателя.Обороты или РегистрНакопления.ТоварыНаСкладах.Остатки) часто требуют особого подхода к фильтрации по датам. Здесь нельзя использовать стандартные функции вроде НАЧАЛОПЕРИОДА() — нужно явно указывать параметры.

Пример корректного запроса к виртуальной таблице остатков:

ВЫБРАТЬ

ОстаткиТоваров.Номенклатура КАК Номенклатура,

ОстаткиТоваров.КоличествоОстаток КАК Остаток

ИЗ

РегистрНакопления.ТоварыНаСкладах.Остатки(

&НачалоПериода,

&КонецПериода,

Номенклатура В (&СписокНоменклатуры)

) КАК ОстаткиТоваров

Ключевые моменты:

  • 🔹 Виртуальные таблицы всегда требуют явного указания периода (даже если он равен одному дню)
  • 🔹 Параметры периода передаются как отдельные аргументы, а не через ГДЕ
  • 🔹 Для таблиц оборотов можно использовать Периодичность (например, ДЕНЬ, МЕСЯЦ)

☑️ Проверка запроса к виртуальной таблице

Выполнено: 0 / 4

6. Оптимизация запросов с датами

Запросы с фильтрацией по датам могут становиться "узким местом" производительности, особенно в больших базах. Вот ключевые правила оптимизации:

  1. Индексы: Убедитесь, что поля дат проиндексированы в метаданных (свойство Индексировать). Без индекса фильтрация по дате приводит к полному сканированию таблицы.
  2. Параметры vs константы: Используйте параметры запроса (&Параметр) вместо жестко заданных дат — это позволяет 1С кэшировать план выполнения.
  3. Избегайте функций в ГДЕ: Конструкции вроде ГДЕ ГОД(Документ.Дата) = 2026 не используют индексы. Заменяйте их на ГДЕ Документ.Дата >= ДАТАВРЕМЯ(2026,1,1) И Документ.Дата < ДАТАВРЕМЯ(2026,1,1).

Для сложных отчетов с группировкой по периодам (неделям, кварталам) используйте материализованные представления или внешние источники данных, если объем данных превышает 100 000 записей.

💡

Самый быстрый способ фильтрации по дате — использование параметров запроса с индексированными полями и прямым сравнением (>=, <), без функций преобразования.

7. Типовые ошибки и их решения

Даже опытные разработчики сталкиваются с неожиданными ошибками при работе с датами. Вот самые распространенные ловушки:

ОшибкаПричинаРешение
Ошибка приведения типа к датеПередача пустой строки или некорректного формата в ДАТАВРЕМЯ()Используйте ВЫРАЗИТЬ(ЗНАЧЕНИЕЗАПОЛНЕНО(..)) КАК ДАТА с проверкой на NULL
Не попадают документы за крайнюю датуИспользование МЕЖДУ с датами, содержащими времяЗаменяйте на два отдельных условия с ДОБАВИТЬКДАТЕ()
Разные результаты на сервере и клиентеЧасовые пояса или настройки сеансаЯвно указывайте часовой пояс в ДАТАВРЕМЯ() или используйте ТЕКУЩАЯДАТАСЕРВЕРА()

Особенно коварна ситуация, когда запрос не падает с ошибкой, но возвращает неверные данные. Например, при сравнении даты с временем (14:30:00) и даты без времени (00:00:00) результат может отличаться от ожидаемого. Всегда проверяйте формат данных в отладчике!

FAQ: Частые вопросы по датам в запросах 1С

Как в запросе получить первый и последний день месяца?

Используйте комбинацию НАЧАЛОПЕРИОДА() и КОНЕЦПЕРИОДА():

ВЫБРАТЬ

НАЧАЛОПЕРИОДА(&ЛюбаяДата, "МЕСЯЦ") КАК ПервыйДень,

КОНЕЦПЕРИОДА(&ЛюбаяДата, "МЕСЯЦ") КАК ПоследнийДень

Если нужны первый/последний день текущего месяца, замените &ЛюбаяДата на ТЕКУЩАЯДАТА().

Почему запрос с МЕЖДУ не включает документы за последнюю дату?

Это происходит, если в переменной &КонецПериода указано ненулевое время. Например, ДАТАВРЕМЯ(2026,5,15,23,59,59) не попадёт в интервал МЕЖДУ.. И ДАТАВРЕМЯ(2026,5,15,23,59,59), потому что МЕЖДУ включает только даты с временем 00:00:00.

Решение: используйте два отдельных условия или обнуляйте время с помощью НАЧАЛОДНЯ().

Как сравнить дату без учёта времени?

Преобразуйте дату к началу дня с помощью НАЧАЛОДНЯ():

ГДЕ НАЧАЛОДНЯ(Документ.Дата) = НАЧАЛОДНЯ(&СравниваемаяДата)

Это гарантированно сравнит только календарные даты, игнорируя часы, минуты и секунды.

Можно ли в запросе использовать даты в формате "15 мая 2026"?

Нет, язык запросов 1С не поддерживает текстовые месяцы ("январь", "май" и т.д.). Используйте либо числовые параметры (ДАТАВРЕМЯ(2026,5,15)), либо строковый формат YYYYMMDD (ДАТАВРЕМЯ("20260515")).

Для вывода даты в текстовом формате используйте ФОРМАТ(Дата, "ДФ='d MMMM yyyy'") уже после выполнения запроса.

Как оптимизировать запрос с группировкой по неделям?

Используйте функцию НАЧАЛОНЕДЕЛИ() в комбинации с ГРУППИРОВКА ПО:

ВЫБРАТЬ

НАЧАЛОНЕДЕЛИ(Документ.Дата) КАК Неделя,

СУММА(Документ.Сумма) КАК Итого

ИЗ

Документ.ЗаказПокупателя КАК Документ

ГДЕ

Документ.Дата МЕЖДУ &НачалоПериода И &КонецПериода

СГРУППИРОВАТЬ ПО

НАЧАЛОНЕДЕЛИ(Документ.Дата)

Для ускорения добавьте в запрос условие по индексированному полю даты до применения функции НАЧАЛОНЕДЕЛИ().