Работа с датами в запросах 1С — одна из самых востребованных операций при разработке отчётов, обработок и аналитических выборок. Даже простая задача вроде фильтрации документов по периоду может превратиться в головоломку, если не знать нюансов синтаксиса 1С:Предприятие. В этой статье разберём все способы указания дат — от элементарных литералов до динамических выражений с функциями, а также типичные ошибки, которые допускают даже опытные программисты.
Особенность работы с датами в 1С заключается в том, что платформа использует собственный формат хранения (Дата), который отличается от стандартного SQL. Это означает, что прямой перенос знаний из других СУБД здесь не сработает. К тому же, начиная с версии 8.3.14, появились новые возможности для работы с временными интервалами, которые многие до сих пор не используют. Если вы когда-нибудь получали ошибку "Недопустимое значение параметра (параметр номер 1)" при попытке отфильтровать данные по дате — эта статья поможет разобраться в причинах.
1. Базовый синтаксис: как указать дату в запросе
Самый простой способ задать дату в запросе — использовать литерал даты. В 1С он записывается в квадратных скобках с ключевым словом ДАТА:
ВЫБРАТЬ
Документ.Ссылка КАК Ссылка
ИЗ
Документ.ПоступлениеТоваров КАК Документ
ГДЕ
Документ.Дата = ДАТА(2026, 05, 15)
В этом примере мы выбираем все документы ПоступлениеТоваров, дата которых строго равна 15 мая 2026 года. Обратите внимание на формат: сначала год, затем месяц (с ведущим нулём, если месяц < 10), потом день. Если указать ДАТА(2026, 5, 15) без нуля, запрос всё равно сработает, но это считается плохим стилем кодирования.
- 📅 Точная дата:
ДАТА(ГГГГ, ММ, ДД)— подходит для фильтрации по конкретному дню. - 🕒 Дата и время:
ДАТАВРЕМЯ(ГГГГ, ММ, ДД, чч, мм, сс)— если нужно учитывать временную составляющую. - 🔄 Текущая дата:
ТЕКУЩАЯДАТА()— возвращает сегодняшний день на момент выполнения запроса.
Важно понимать, что литерал ДАТА создаёт значение типа Дата, а не строку. Это означает, что сравнение Документ.Дата = "15.05.2026" (со строкой) не сработает — 1С выдаст ошибку несоответствия типов. Это одна из самых распространённых ошибок новичков.
Если вам нужно сравнить дату с пустым значением, используйте конструкцию Документ.Дата ЕСТЬ NULL вместо Документ.Дата = NULL. Последний вариант приведёт к синтаксической ошибке.
2. Диапазоны дат: между, больше/меньше, в текущем месяце
Чаще всего требуется выбрать документы не за один день, а за период. Для этого используются операторы сравнения и функция МЕЖДУ:
ВЫБРАТЬ
Документ.Ссылка,
Документ.Дата
ИЗ
Документ.РеализацияТоваров КАК Документ
ГДЕ
Документ.Дата МЕЖДУ ДАТА(2026, 01, 01) И ДАТА(2026, 01, 31)
Оператор МЕЖДУ включает обе границы диапазона. Если нужно исключить одну из дат, используйте явные сравнения:
ГДЕ
Документ.Дата >= ДАТА(2026, 01, 01)
И Документ.Дата < ДАТА(2026, 02, 01)
Для динамических периодов (например, "текущий месяц" или "последняя неделя") используйте функции работы с датами:
- 📅 Начало месяца:
НАЧАЛОМЕСЯЦА(ТЕКУЩАЯДАТА()) - 📅 Конец месяца:
КОНЕЦМЕСЯЦА(ТЕКУЩАЯДАТА()) - 📅 Начало года:
НАЧАЛОГОДА(ТЕКУЩАЯДАТА()) - 📅 Добавить дни:
ДОБАВИТЬМЕСЯЦ(ТЕКУЩАЯДАТА(), -1)(предыдущий месяц)
Пример запроса для выборки данных за текущий месяц:
ВЫБРАТЬ
Документ.Номер,
Документ.СуммаДокумента
ИЗ
Документ.ЗаказПокупателя КАК Документ
ГДЕ
Документ.Дата >= НАЧАЛОМЕСЯЦА(ТЕКУЩАЯДАТА())
И Документ.Дата <= КОНЕЦМЕСЯЦА(ТЕКУЩАЯДАТА())
3. Работа с параметрами: как передать дату из кода в запрос
В реальных задачах даты редко жёстко прописаны в запросе — обычно они передаются как параметры. Это позволяет гибко менять периоды без правки кода. Для этого используется конструкция &Параметр:
ЗАПРОС = Новый Запрос;
ЗАПРОС.Текст =
"ВЫБРАТЬ
| Документ.Дата КАК Дата,
| Документ.Сумма КАК Сумма
|ИЗ
| Документ.Оплаты КАК Документ
|ГДЕ
| Документ.Дата >= &ДатаНачала
| И Документ.Дата <= &ДатаОкончания";
ЗАПРОС.УстановитьПараметр("ДатаНачала", НачалоМесяца(ТекущаяДата()));
ЗАПРОС.УстановитьПараметр("ДатаОкончания", КонецМесяца(ТекущаяДата()));
Ключевые моменты при работе с параметрами:
- Имена параметров в запросе должны начинаться с
&(например,&ДатаНачала). - Перед выполнением запроса обязательно установите значения параметров методом
УстановитьПараметр(). - Тип параметра должен соответствовать типу поля в базе. Например, если поле имеет тип
Дата, передавайте именно Дата, а не строку.
Типичная ошибка — передача строки вместо даты:
// НЕПРАВИЛЬНО!
ЗАПРОС.УстановитьПараметр("ДатаНачала", "01.05.2026");
Это приведёт к ошибке приведения типов. Всегда преобразуйте строку в дату заранее:
ДатаНачала = Дата(2026, 5, 1);
ЗАПРОС.УстановитьПараметр("ДатаНачала", ДатаНачала);
Убедиться, что все параметры установлены|Проверить соответствие типов параметров и полей БД|Заменить строковые даты на тип Дата|Проверить границы диапазона (начало <= конец)-->
4. Сложные сценарии: работа с временными интервалами и календарными функциями
Иногда требуется не просто отфильтровать данные по дате, а произвести более сложные манипуляции — например, сгруппировать по неделям, кварталам или вычислить разницу между датами. Для этого в языке запросов 1С предусмотрены специальные функции:
| Функция | Описание | Пример использования |
|---|---|---|
НАЧАЛОПЕРИОДА() |
Возвращает начало периода (день, неделя, месяц, квартал, год) | НАЧАЛОПЕРИОДА(Документ.Дата, "Месяц") |
КОНЕЦПЕРИОДА() |
Возвращает конец периода | КОНЕЦПЕРИОДА(Документ.Дата, "Квартал") |
ДОБАВИТЬКДАТЕ() |
Добавляет заданное количество единиц (дни, месяцы, годы) | ДОБАВИТЬКДАТЕ(Документ.Дата, "День", 7) |
РАЗНОСТЬДАТ() |
Возвращает разницу между датами в заданных единицах | РАЗНОСТЬДАТ("День", Документ.Дата, ТЕКУЩАЯДАТА()) |
Пример запроса, который группирует документы по кварталам и считает сумму продаж:
ВЫБРАТЬ
НАЧАЛОПЕРИОДА(Документ.Дата, "Квартал") КАК Квартал,
СУММА(Документ.СуммаДокумента) КАК СуммаПродаж
ИЗ
Документ.РеализацияТоваров КАК Документ
ГДЕ
Документ.Дата >= НАЧАЛОГОДА(ТЕКУЩАЯДАТА())
СГРУППИРОВАТЬ ПО
НАЧАЛОПЕРИОДА(Документ.Дата, "Квартал")
Обратите внимание, что функция НАЧАЛОПЕРИОДА может принимать следующие значения для параметра ТипПериода:
- 📅
"День"— начало дня (00:00:00) - 📅
"Неделя"— начало недели (понедельник) - 📅
"Декада"— начало декады (1-е, 11-е или 21-е число месяца) - 📅
"Месяц"— первое число месяца - 📅
"Квартал"— начало квартала (1 января, 1 апреля, 1 июля, 1 октября)
Как 1С определяет начало недели?
По умолчанию в 1С неделю начинается с понедельника (стандарт ISO 8601). Однако это можно изменить в настройках информационной базы через параметр НачалоНедели в объекте Календарь. В некоторых локализациях (например, для США) начало недели может быть установлено на воскресенье.
5. Типичные ошибки и как их избежать
Даже опытные разработчики иногда сталкиваются с неожиданными ошибками при работе с датами в запросах. Вот наиболее распространённые проблемы и способы их решения:
⚠️ Внимание: Если вы используетеДАТАВРЕМЯв запросе, а поле в базе имеет типДата(без времени), сравнение может не сработать из-за неявного приведения типов. Всегда приводите типы к одному виду с помощьюНАЧАЛОДНЯ().
- ❌ Ошибка приведения типов: Сравнение даты со строкой (
Документ.Дата = "15.05.2026"). Решение: ИспользуйтеДАТА(2026, 05, 15). - ❌ Неверный формат даты: Указание месяца без ведущего нуля (
ДАТА(2026, 5, 15)). Решение: Всегда используйте двузначный месяц (05). - ❌ Пустые параметры: Забыли установить параметр перед выполнением запроса. Решение: Проверяйте установку параметров через
Запрос.Параметры.Свойство(). - ❌ Проблемы с временными зонами: В распределённых базах даты могут отличаться из-за настроек сервера. Решение: Используйте
ТЕКУЩАЯДАТА()на сервере, а не на клиенте.
Ещё одна распространённая ошибка — неучёт времени при сравнении дат. Например, если в базе хранится ДатаВремя, а вы сравниваете с ДАТА(2026, 05, 15), то документы, созданные 15 мая после 00:00, не попадут в выборку. Чтобы этого избежать, используйте:
ГДЕ
НАЧАЛОДНЯ(Документ.Дата) = ДАТА(2026, 05, 15)
Это гарантирует, что будут выбраны все документы за указанный календарный день, независимо от времени.
Всегда проверяйте тип поля в метаданных (Дата или ДатаВремя) и используйте соответствующие функции для сравнения. Для полей типа ДатаВремя обязательно применяйте НАЧАЛОДНЯ(), если вам нужны документы за весь день.
6. Оптимизация запросов с датами: индексы и производительность
Запросы с фильтрацией по датам могут тормозить, если не учтены особенности хранения данных в 1С. Вот несколько советов для ускорения работы:
- Используйте индексы: Убедитесь, что по полю
Датав таблице базы данных создан индекс. В 1С индексы создаются автоматически для полей, участвующих в отборах, но в некоторых случаях (например, для виртуальных таблиц) может потребоваться ручная настройка. - Избегайте функций в условиях: Запрос
ГДЕ ГОД(Документ.Дата) = 2026будет работать медленнее, чемГДЕ Документ.Дата >= ДАТА(2026, 01, 01) И Документ.Дата < ДАТА(2026, 01, 01), потому что функцияГОД()не позволяет использовать индексы. - Ограничивайте диапазоны: Если вам нужны данные за последний месяц, не запрашивайте весь год. Чем уже диапазон, тем быстрее выполнится запрос.
Пример неоптимального и оптимизированного запроса:
// НЕОПТИМАЛЬНО (функция в условии)
ВЫБРАТЬ
Документ.Ссылка
ИЗ
Документ.ПоступлениеТоваров КАК Документ
ГДЕ
ГОД(Документ.Дата) = 2026
И МЕСЯЦ(Документ.Дата) = 5
// ОПТИМАЛЬНО (прямое сравнение)
ВЫБРАТЬ
Документ.Ссылка
ИЗ
Документ.ПоступлениеТоваров КАК Документ
ГДЕ
Документ.Дата >= ДАТА(2026, 05, 01)
И Документ.Дата < ДАТА(2026, 06, 01)
Для анализа производительности запросов используйте план выполнения. В конфигураторе 1С его можно получить так:
Объяснение = ЗАПРОС.Выполнить().Объяснить();
Это поможет выявить "узкие места" и оптимизировать запрос.
7. Работа с датами в разных версиях 1С: 8.2 vs 8.3
Синтаксис работы с датами в запросах 1С практически не изменился между версиями 8.2 и 8.3, но есть несколько важных нюансов:
- 🔹 В 1С:Предприятие 8.3 появилась поддержка расширенного синтаксиса для работы с временными рядами (например, функции
ПЕРИОДЫдля генерации последовательностей дат). - 🔹 В версии 8.3.14+ добавлена возможность использования
ДАТАВРЕМЯс миллисекундами, что актуально для высоконагруженных систем с точным учётом времени. - 🔹 В 8.2 отсутствует функция
РАЗНОСТЬДАТ— её приходилось эмулировать через вычитание дат и деление на количество секунд в дне.
Пример использования ПЕРИОДЫ (доступно только в 8.3):
ВЫБРАТЬ
Календарь.Период КАК Период
ПОМЕСТИТЬ ВТПериоды
ИЗ
ПЕРИОДЫ(ДАТА(2026, 01, 01), ДАТА(2026, 12, 31), МЕСЯЦ) КАК Календарь
Этот запрос создаёт временную таблицу с месяцами за 2026 год, которую затем можно использовать для левого соединения с документами.
⚠️ Внимание: Если вы поддерживаете конфигурации на версии 8.2, избегайте функций, появившихся в 8.3 (например,РАЗНОСТЬДАТ). Для обратной совместимости используйте универсальные конструкции или проверяйте версию платформы черезПлатформа83().
8. Практический пример: сложный запрос с датами и группировкой
Рассмотрим реальную задачу: нужно получить сумму продаж по контрагентам за каждый месяц текущего года, с сравнением с аналогичным периодом прошлого года.
ВЫБРАТЬ
Контрагент.Наименование КАК Контрагент,
НАЧАЛОПЕРИОДА(Документ.Дата, "Месяц") КАК Месяц,
СУММА(Документ.СуммаДокумента) КАК СуммаТекущийГод,
(
ВЫБРАТЬ СУММА(ДокЛП.СуммаДокумента)
ИЗ Документ.РеализацияТоваров КАК ДокЛП
ГДЕ
ДокЛП.Контрагент = Документ.Контрагент
И НАЧАЛОПЕРИОДА(ДокЛП.Дата, "Месяц") = ДОБАВИТЬМЕСЯЦ(НАЧАЛОПЕРИОДА(Документ.Дата, "Месяц"), -12)
) КАК СуммаПрошлыйГод
ИЗ
Документ.РеализацияТоваров КАК Документ
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК Контрагент
ПО Документ.Контрагент = Контрагент.Ссылка
ГДЕ
Документ.Дата >= НАЧАЛОГОДА(ТЕКУЩАЯДАТА())
И Документ.Дата < НАЧАЛОГОДА(ДОБАВИТЬГОД(ТЕКУЩАЯДАТА(), 1))
СГРУППИРОВАТЬ ПО
Контрагент.Наименование,
НАЧАЛОПЕРИОДА(Документ.Дата, "Месяц")
В этом запросе:
- Мы группируем продажи по контрагентам и месяцам.
- Для каждого месяца текущего года считаем сумму продаж.
- Через подзапрос получаем сумму продаж за тот же месяц прошлого года.
- Используем
ДОБАВИТЬМЕСЯЦ(..., -12)для смещения на год назад.
Важно: Подзапросы в 1С могут значительно замедлять выполнение. Если база большая, рассмотрите вариант с временными таблицами или переносом логики в программный код.
Для сложных аналитических запросов с сравнением периодов лучше использовать механизм временных таблиц или выносить часть логики в программный код (например, через Объект.ВыполнитьЗапросПакетом).
Часто задаваемые вопросы
Как в запросе 1С получить первую и последнюю дату месяца?
Используйте функции НАЧАЛОМЕСЯЦА() и КОНЕЦМЕСЯЦА(). Пример:
ВЫБРАТЬ
НАЧАЛОМЕСЯЦА(ТЕКУЩАЯДАТА()) КАК ПервыйДень,
КОНЕЦМЕСЯЦА(ТЕКУЩАЯДАТА()) КАК ПоследнийДень
Для произвольной даты замените ТЕКУЩАЯДАТА() на нужное значение.
Почему запрос с датой возвращает пустой результат, хотя документы есть?
Наиболее вероятные причины:
- Поле в базе имеет тип
ДатаВремя, а вы сравниваете сДата(или наоборот). ИспользуйтеНАЧАЛОДНЯ(). - Неверно указан формат даты (например, месяц без ведущего нуля).
- Проблемы с временными зонами в распределённой базе. Проверьте настройки кластера.
Для диагностики выполните запрос без фильтра по дате и проверьте реальные значения в поле.
Как в запросе получить разницу между двумя датами в днях?
В 1С 8.3 используйте функцию РАЗНОСТЬДАТ():
ВЫБРАТЬ
РАЗНОСТЬДАТ("День", Документ.Дата, ТЕКУЩАЯДАТА()) КАК ДнейНазад
В 8.2 придётся вычислять вручную:
ВЫБРАТЬ
ЦЕЛ(ТЕКУЩАЯДАТА() - Документ.Дата) КАК ДнейНазад
Можно ли в запросе 1С использовать даты в формате ISO (YYYY-MM-DD)?
Нет, 1С не поддерживает ISO-формат напрямую в литералах дат. Однако вы можете:
- Использовать стандартный синтаксис:
ДАТА(2026, 05, 15). - Преобразовать строку в дату через
Дата(Год, Месяц, День)в программном коде перед передачей в запрос.
Пример преобразования строки "2026-05-15":
ДатаДок = Дата(Число(Лев("2026-05-15", 4)), Число(Сред("2026-05-15", 6, 2)), Число(Прав("2026-05-15", 2)));
Как в запросе отфильтровать документы за последние 30 дней?
Используйте функцию ДОБАВИТЬДЕНЬ():
ВЫБРАТЬ
Документ.Ссылка
ИЗ
Документ.ПоступлениеТоваров КАК Документ
ГДЕ
Документ.Дата >= ДОБАВИТЬДЕНЬ(ТЕКУЩАЯДАТА(), -30)
Для точности можно добавить НАЧАЛОДНЯ():
ГДЕ Документ.Дата >= НАЧАЛОДНЯ(ДОБАВИТЬДЕНЬ(ТЕКУЩАЯДАТА(), -30))