Работа с датами в запросах 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. Работа с параметрами: как передать дату из кода в запрос

В реальных задачах даты редко жёстко прописаны в запросе — обычно они передаются как параметры. Это позволяет гибко менять периоды без правки кода. Для этого используется конструкция &Параметр:

ЗАПРОС = Новый Запрос;

ЗАПРОС.Текст =

"ВЫБРАТЬ

| Документ.Дата КАК Дата,

| Документ.Сумма КАК Сумма

|ИЗ

| Документ.Оплаты КАК Документ

|ГДЕ

| Документ.Дата >= &ДатаНачала

| И Документ.Дата <= &ДатаОкончания";

ЗАПРОС.УстановитьПараметр("ДатаНачала", НачалоМесяца(ТекущаяДата()));

ЗАПРОС.УстановитьПараметр("ДатаОкончания", КонецМесяца(ТекущаяДата()));

Ключевые моменты при работе с параметрами:

  1. Имена параметров в запросе должны начинаться с & (например, &ДатаНачала).
  2. Перед выполнением запроса обязательно установите значения параметров методом УстановитьПараметр().
  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. Используйте индексы: Убедитесь, что по полю Дата в таблице базы данных создан индекс. В 1С индексы создаются автоматически для полей, участвующих в отборах, но в некоторых случаях (например, для виртуальных таблиц) может потребоваться ручная настройка.
  2. Избегайте функций в условиях: Запрос ГДЕ ГОД(Документ.Дата) = 2026 будет работать медленнее, чем ГДЕ Документ.Дата >= ДАТА(2026, 01, 01) И Документ.Дата < ДАТА(2026, 01, 01), потому что функция ГОД() не позволяет использовать индексы.
  3. Ограничивайте диапазоны: Если вам нужны данные за последний месяц, не запрашивайте весь год. Чем уже диапазон, тем быстрее выполнится запрос.

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

// НЕОПТИМАЛЬНО (функция в условии)

ВЫБРАТЬ

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

ИЗ

Документ.ПоступлениеТоваров КАК Документ

ГДЕ

ГОД(Документ.Дата) = 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))

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

Контрагент.Наименование,

НАЧАЛОПЕРИОДА(Документ.Дата, "Месяц")

В этом запросе:

  1. Мы группируем продажи по контрагентам и месяцам.
  2. Для каждого месяца текущего года считаем сумму продаж.
  3. Через подзапрос получаем сумму продаж за тот же месяц прошлого года.
  4. Используем ДОБАВИТЬМЕСЯЦ(..., -12) для смещения на год назад.

Важно: Подзапросы в 1С могут значительно замедлять выполнение. Если база большая, рассмотрите вариант с временными таблицами или переносом логики в программный код.

💡

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

Часто задаваемые вопросы

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

Используйте функции НАЧАЛОМЕСЯЦА() и КОНЕЦМЕСЯЦА(). Пример:

ВЫБРАТЬ

НАЧАЛОМЕСЯЦА(ТЕКУЩАЯДАТА()) КАК ПервыйДень,

КОНЕЦМЕСЯЦА(ТЕКУЩАЯДАТА()) КАК ПоследнийДень

Для произвольной даты замените ТЕКУЩАЯДАТА() на нужное значение.

Почему запрос с датой возвращает пустой результат, хотя документы есть?

Наиболее вероятные причины:

  1. Поле в базе имеет тип ДатаВремя, а вы сравниваете с Дата (или наоборот). Используйте НАЧАЛОДНЯ().
  2. Неверно указан формат даты (например, месяц без ведущего нуля).
  3. Проблемы с временными зонами в распределённой базе. Проверьте настройки кластера.

Для диагностики выполните запрос без фильтра по дате и проверьте реальные значения в поле.

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

В 1С 8.3 используйте функцию РАЗНОСТЬДАТ():

ВЫБРАТЬ

РАЗНОСТЬДАТ("День", Документ.Дата, ТЕКУЩАЯДАТА()) КАК ДнейНазад

В 8.2 придётся вычислять вручную:

ВЫБРАТЬ

ЦЕЛ(ТЕКУЩАЯДАТА() - Документ.Дата) КАК ДнейНазад

Можно ли в запросе 1С использовать даты в формате ISO (YYYY-MM-DD)?

Нет, 1С не поддерживает ISO-формат напрямую в литералах дат. Однако вы можете:

  1. Использовать стандартный синтаксис: ДАТА(2026, 05, 15).
  2. Преобразовать строку в дату через Дата(Год, Месяц, День) в программном коде перед передачей в запрос.

Пример преобразования строки "2026-05-15":

ДатаДок = Дата(Число(Лев("2026-05-15", 4)), Число(Сред("2026-05-15", 6, 2)), Число(Прав("2026-05-15", 2)));
Как в запросе отфильтровать документы за последние 30 дней?

Используйте функцию ДОБАВИТЬДЕНЬ():

ВЫБРАТЬ

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

ИЗ

Документ.ПоступлениеТоваров КАК Документ

ГДЕ

Документ.Дата >= ДОБАВИТЬДЕНЬ(ТЕКУЩАЯДАТА(), -30)

Для точности можно добавить НАЧАЛОДНЯ():

ГДЕ Документ.Дата >= НАЧАЛОДНЯ(ДОБАВИТЬДЕНЬ(ТЕКУЩАЯДАТА(), -30))