Работа с датами — это фундаментальная задача при разработке сложных отчетов и аналитических выборок в системе 1С:Предприятие. Именно временные метки позволяют фильтровать документы, строить оборотно-сальдовые ведомости и анализировать динамику продаж. Неправильная передача даты в запрос 1С может привести к тому, что отчет покажет пустые результаты или, наоборот, выборку за неверный период.

Механизм работы с временными отрезками в языке запросов имеет свои особенности синтаксиса, которые отличают его от стандартного SQL. Понимание этих нюансов критически важно для разработчиков, так как движок запросов 1С автоматически обрабатывает типы данных, но требует строгого соблюдения формата литералов. Давайте разберем, как корректно сформировать условие отбора и избежать распространенных ошибок при фильтрации по времени.

Синтаксис литералов даты в запросах

В языке запросов платформы 1С существует специальный тип данных — Дата, который позволяет оперировать моментами времени с точностью до секунды. Для того чтобы явно указать дату в тексте запроса, необходимо использовать специальный формат записи, заключенный в фигурные скобки. Это отличает дату от строковых констант и числовых значений.

Базовый формат записи выглядит следующим образом: дата заключается в фигурные скобки {}, внутри которых указывается значение в кавычках. Стандартный вид литерала даты — {'ГГГГ-ММ-ДД'}. Например, чтобы обратиться к 1 января 2026 года, вы должны написать {'2026-01-01'}.

Если требуется указать не только дату, но и конкретное время, синтаксис расширяется. Вы можете добавить время через пробел после даты в формате ЧЧ:ММ:СС. Пример полного литерала: {'2026-01-01 14:30:00'}. При этом система автоматически приведет неполные значения к началу или концу периода, если время не указано явно, что важно учитывать при сравнении с документами, имеющими временную привязку.

Особое внимание стоит уделить тому, как платформа обрабатывает такие литералы на уровне компиляции. В отличие от параметров, которые подставляются во время выполнения, жестко заданные в тексте даты фиксируются в дереве метаданных. Это может повлиять на перекомпиляцию запроса при изменении констант в коде, поэтому для динамических отчетов лучше использовать параметры.

Использование параметров для динамической фильтрации

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

Параметр в тексте запроса обозначается знаком двоеточия : перед его именем. Например, условие отбора по дате документа может выглядеть так: Где Документ.Дата > :НачалоПериода. Значение для параметра НачалоПериода передается в объект Запрос программно перед выполнением. Это дает гибкость: один и тот же текст запроса может работать для любого выбранного пользоватлем периода.

При установке значения параметра важно соблюдать типизацию. Если в запросе ожидается дата, то в метод УстановитьПараметр необходимо передать значение типа Дата. Платформа автоматически преобразует строковое представление в дату, если это возможно, но явное приведение типов считается хорошим тоном программирования и страхует от ошибок в пограничных случаях.

📊 Как вы чаще всего передаете дату в запрос?
Жестко в тексте запроса
Через параметры запроса
Через временные таблицы
Использую СКД без запросов

Рассмотрим пример программного заполнения параметров. В модуле объекта или форме отчета вы создаете объект запроса, получаете его текст, а затем назначаете значения. Код может выглядеть так:

Запрос = Новый Запрос;

Запрос.Текст = "ВЫБРАТЬ.. ГДЕ Дата > :НачПериода";

Запрос.УстановитьПараметр("НачПериода", НачалоДня(ДатаНач));

Запрос.УстановитьПараметр("КонПериода", КонецДня(ДатаКон));

Результат = Запрос.Выполнить();

Такой подход гарантирует, что даже если пользователь выберет "Сегодня" или "Прошлый месяц", запрос сформируется корректно. Кроме того, использование параметров позволяет движку 1С эффективнее кэшировать планы выполнения запросов, так как структура запроса не меняется, меняются только входные данные.

Сравнение дат и учет времени в условиях

Одной из самых частых проблем при разработке является некорректный отбор документов за определенный день. Это связано с тем, что тип Дата в 1С хранит не только календарный день, но и время. Если вы напишете условие Где Дата = {'2026-05-20'}, система интерпретирует это как 2026-05-20 00:00:00.

В результате в выборку попадут только те документы, которые были проведены ровно в полночь. Все документы, созданные днем (например, в 10:15 или 16:45), будут отсечены, так как их время не совпадает с нулевым. Чтобы избежать этой логической ошибки, необходимо использовать диапазоны или специальные функции.

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

  • 📅 Используйте конструкцию Дата >= :НачалоДня И Дата < :НачалоСледующегоДня для полного охвата суток.
  • ⏰ Функция НачалоДня() обнуляет время, устанавливая его в 00:00:00.
  • 🚫 Избегайте сравнения на равенство (=) для полей типа Дата, если не уверены, что время тоже совпадает.
⚠️ Внимание: При использовании условия "меньше или равно" (<=) с концом дня КонецДня(), вы можете пропустить документы, проведенные в последние секунды суток (23:59:59.999), из-за особенностей округления. Безопаснее использовать строго меньше (<) начала следующего дня.

Также стоит упомянуть функцию Период, которая иногда используется в конструкторах запросов, но в ручном написании кода явное указание границ диапазона является более прозрачным и производительным решением. Это позволяет базе данных использовать индексы по полю даты наиболее эффективным образом.

Работа с отчетными периодами и границами

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

Функции НачалоПериода и КонецПериода (или их аналоги НачалоМесяца, КонецМесяца) являются незаменимыми инструментами. Они принимают дату любого дня внутри искомого периода и возвращают соответствующую границу. Например, передав в функцию дату 15 марта, вы получите 1 марта или 31 марта соответственно.

Использование этих функций прямо в тексте запроса возможно, но имеет свои нюансы производительности. Если функция применяется к полю таблицы (например, НачалоМесяца(Документ.Дата)), это может привести к полному сканированию таблицы (Table Scan), так как значение поля изменяется на лету и индекс по исходной дате не может быть использован.

💡

Всегда вычисляйте границы периода в коде перед выполнением запроса и передавайте их как параметры. Это позволит СУБД использовать индекс по полю даты, что ускорит работу отчета в десятки раз на больших объемах данных.

Лучшей практикой считается вычисление границ периода в коде на языке 1С и передача готовых значений в параметры запроса. Это перекладывает вычислительную нагрузку с сервера базы данных на клиент или сервер приложений, где это часто менее критично, и сохраняет возможность использования индексов.

Рассмотрим таблицу популярных функций для работы с периодами, которые могут пригодиться при формировании условий отбора:

Функция Описание Пример результата для 15.05.2026
НачалоДня() Возвращает начало текущего дня 15.05.2026 00:00:00
НачалоМесяца() Возвращает первое число месяца 01.05.2026 00:00:00
КонецМесяца() Возвращает последний день месяца 31.05.2026 23:59:59
НачалоКвартала() Возвращает первый день квартала 01.04.2026 00:00:00

Правильное использование этих функций позволяет строить гибкие отчеты, такие как "Обороты за текущий месяц" или "Анализ продаж с начала года", без необходимости жесткой привязки к календарю в коде программы.

Особенности работы с NULL и неопределенными датами

В базах данных 1С поле типа Дата может содержать специальное значение NULL (неопределено). Это состояние отличается от любой конкретной даты, включая самую раннюю или самую позднюю возможную. При написании условий отбора необходимо четко понимать, как система обрабатывает такие значения.

Стандартные операторы сравнения (=, >, <) не работают с NULL так, как ожидают новички. Выражение Где Дата = NULL всегда вернет ложь, и строки с неопределенной датой не попадут в выборку. Для проверки на неопределенность существует специальный синтаксис: Где Дата ЕСТЬ NULL.

Аналогично, для отбора всех записей, где дата заполнена (не является пустой), используется конструкция Где Дата ЕСТЬ НЕ NULL. Это часто требуется при поиске документов, которые еще не были проведены или у которых не установлена дата оплаты.

Почему NULL не равен NULL?

В логике баз данных NULL означает "неизвестное значение". Сравнение двух неизвестных значений не может дать истину, поэтому результат всегда неизвестен (False в контексте фильтрации). Для проверки используется специальный оператор ЕСТЬ NULL.

Частой ошибкой является попытка заменить проверку на NULL сравнением с датой начала эры (например, {'0001-01-01'}). В 1С такое сравнение технически возможно, но семантически неверно, так как пустая дата и минимальная дата — это разные сущности. Использование правильного синтаксиса делает код читаемым и предсказуемым.

Типичные ошибки и способы их устранения

Даже опытные разработчики иногда допускают ошибки при работе с датами в запросах. Чаще всего они связаны с незнанием особенностей формата литералов или игнорированием временной составляющей. Разберем несколько распространенных сценариев, которые приводят к нерабочим отчетам.

Первая ошибка — использование неверного разделителя в литерале даты. Попытка написать {'20.05.2026'} вызовет ошибку синтаксиса при компиляции запроса. Язык запросов 1С строго требует формата ГГГГ-ММ-ДД. Это международный стандарт ISO 8601, который исключает двусмысленность между американским и европейским форматами.

Вторая распространенная проблема — потеря данных из-за неправильного оператора сравнения. Как упоминалось ранее, использование <= КонецДня() может отсечь документы, созданные в доли секунды до полуночи. Всегда используйте полуоткрытые интервалы: [Начало, Конец), где правая граница не включается.

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

Третья ошибка касается передачи параметров неправильного типа. Если вы пытаетесь передать строку "2026-05-20" в параметр типа Дата, система может выдать ошибку выполнения или неявно преобразовать значение, что не всегда срабатывает корректно в сложных выражениях. Всегда явно создавайте объект Дата перед установкой параметра.

☑️ Проверка корректности даты в запросе

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

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

Оптимизация производительности при фильтрации по датам

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

Главное правило оптимизации — условие по дате должно быть SARGable (Search ARGument Able). Это означает, что поле таблицы не должно участвовать в функциях или вычислениях в левой части условия. Запрос вида Где Год(Дата) = 2026 заставит систему перебрать все записи, вычисляя год для каждой из них.

Вместо этого следует использовать диапазон: Где Дата >= {'2026-01-01'} И Дата < {'2026-01-01'}. Такая формулировка позволяет движку базы данных (MSSQL, PostgreSQL или встроенному) сразу перейти к нужному участку индекса, игнорируя остальные записи. Разница в скорости может составлять сотни раз.

💡

Использование диапазона дат вместо функций над полем даты — ключевой фактор производительности. Индексы работают только с "чистыми" полями в условиях сравнения.

Также стоит избегать приведения типов на лету. Если поле хранит дату, а вы сравниваете его со строковым литералом без явного указания типа даты в фигурных скобках, система может выполнить неявное преобразование, что также негативно скажется на плане выполнения запроса. Всегда используйте типизированные литералы {'..'}.

Что делать, если дата передается из внешнего источника в строковом виде?

Если вы получаете дату в виде строки (например, из веб-сервиса или текстового файла), сначала преобразуйте её в тип Дата с помощью функции Дата() или Попытка..Исключение для валидации. Только после успешного преобразования передавайте значение в параметр запроса. Не пытайтесь подставлять строку напрямую в текст запроса, это нарушит типизацию.

Как передать дату в запрос через систему компоновки данных (СКД)?

В СКД даты передаются через параметры пользовательских настроек. В схеме компоновки данных создайте параметр типа Дата, а в тексте запроса обращайтесь к нему как &ИмяПараметра (через амперсанд). Значение параметра будет автоматически подставлено из настроек отчета при его формировании.

Можно ли использовать дату в группировках запроса?

Да, дату можно использовать в операторе СГРУППИРОВАТЬ ПО. Однако для аналитики чаще используют усеченные даты (например, по месяцам). Для этого лучше вычислять начало месяца в списке полей выборки, присваивать ему псевдоним и группировать уже по этому псевдониму, а не по полному значению даты с временем.

Почему запрос с датой работает медленно на файловой базе?

Файловые версии 1С имеют ограничения в использовании индексов по сравнению с клиент-серверным вариантом (SQL). Если запрос выполняется медленно, убедитесь, что по полю даты установлен индекс в конфигураторе. Также проверьте, не используете ли вы функции над полем даты в условии отбора, так как на файловых базах это особенно критично для производительности.

Как обработать високосный год при расчете периодов?

Функции платформы 1С, такие как КонецМесяца() или ДобавитьМесяц(), автоматически учитывают високосные годы. Вам не нужно писать дополнительную логику для проверки количества дней в феврале. Достаточно передать любую дату февраля високосного года в функцию, и она корректно вернет 29 число.