К статье
Практический материал

Разработка и Конфигурация · 12 мин

Как сравнить время в запросе 1С

Как сравнить время в запросе 1С: операторы сравнения дат, функции НАЧАЛОПЕРИОДА и КОНЕЦПЕРИОДА, отбор по времени суток, типичные ошибки и примеры кода.

Сравнение даты и времени в запросах 1С — одна из базовых задач при построении отчётов, отборе документов за смену, расчёте просрочек и контроле регламентных операций. Язык запросов 1С поддерживает стандартные операторы сравнения (>, <, =, >=, <=, <>) для полей типа «Дата», а также набор функций для работы с периодами и составляющими даты.

Главная сложность в том, что тип «Дата» в 1С всегда содержит и дату, и время с точностью до секунды. Поэтому сравнение «документ за сегодня» через простое равенство почти никогда не сработает: значение 01.03.2026 14:23:05 не равно 01.03.2026 00:00:00. Для корректных отборов нужно либо задавать интервал, либо менять точность сравниваемого значения функциями языка запросов.

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

Как устроен тип «Дата» и почему равенство не работает

В 1С значение типа «Дата» — это всегда комбинация календарной даты и времени суток с точностью до секунды. Даже если в документе время не отображается, физически оно хранится. Поле «Дата» документа содержит, например, 15.06.2026 10:31:47, а не просто «15 июня».

Следствие: условие ГДЕ Документ.Дата = &Дата вернёт записи только при совпадении до секунды. Если в параметр передали дату без времени, она интерпретируется как начало дня 00:00:00, и выборка окажется пустой либо неполной. Это самая частая причина «не работающего» отбора у начинающих разработчиков.

Правильные альтернативы равенству: сравнение через интервал (МЕЖДУ или пара условий), приведение даты к началу периода функцией НАЧАЛОПЕРИОДА или сравнение отдельных компонентов через ДЕНЬ, МЕСЯЦ, ГОД, ЧАС, МИНУТА.

Сравнение даты и времени с параметром запроса

Самый простой сценарий — отобрать записи позже или раньше заданного момента. Параметр объявляется через амперсанд и передаётся из кода методом УстановитьПараметр. Операторы сравнения работают напрямую, без преобразований:

ВЫБРАТЬ

Регистрация.Ссылка КАК Документ,

Регистрация.Дата КАК ДатаДокумента

ИЗ

Документ.Регистрация КАК Регистрация

ГДЕ

Регистрация.Дата >= &МоментНачала

И Регистрация.Дата < &МоментОкончания

Обратите внимание на пару «>= начало, < конец». Такая форма исключает неоднозначность на границе интервала: запись ровно в момент окончания попадёт уже в следующий период. Это стандартный приём при разбиении данных на смены, сутки, месяцы.

Если параметр должен задаваться датой без времени, передайте его через функции НачалоДня() и КонецДня() встроенного языка либо сформируйте границы прямо в запросе через НАЧАЛОПЕРИОДА и КОНЕЦПЕРИОДА.

Как задать отбор по моменту времени
  1. 1
    Объявите параметр в тексте запроса: ГДЕ Таблица.Дата >= &Момент
  2. 2
    В коде передайте значение: Запрос.УстановитьПараметр("Момент", ТекущаяДатаСеанса())
  3. 3
    Для интервала используйте два параметра: начало включительно, конец исключительно
  4. 4
    Выполните запрос и проверьте, что граничные записи попали в выборку ровно один раз

Отбор документов за день, месяц или произвольный период

Для отбора за конкретный день самый надёжный вариант — интервал от начала дня до начала следующего дня. Оператор МЕЖДУ в 1С включает обе границы, поэтому с ним нужна осторожность: запись на границе 23:59:59 учтётся, но при стыковке периодов возможны двойные попадания, если границы заданы как конец и начало одного момента.

ГДЕ

Продажи.Период МЕЖДУ НАЧАЛОПЕРИОДА(&Дата, ДЕНЬ)

И КОНЕЦПЕРИОДА(&Дата, ДЕНЬ)

Функция НАЧАЛОПЕРИОДА(Дата, Период) возвращает начало указанного периода (СЕКУНДА, МИНУТА, ЧАС, ДЕНЬ, НЕДЕЛЯ, МЕСЯЦ, КВАРТАЛ, ГОД), а КОНЕЦПЕРИОДА — соответственно конец. Например, КОНЕЦПЕРИОДА(&Дата, МЕСЯЦ) даст последнюю секунду месяца.

Альтернатива без функций — сравнение приведённого значения: ГДЕ НАЧАЛОПЕРИОДА(Документ.Дата, ДЕНЬ) = НАЧАЛОПЕРИОДА(&Дата, ДЕНЬ). Такой вариант читается проще, но на больших таблицах может работать медленнее, потому что функция применяется к каждой строке и мешает использовать индекс по полю даты.

Как сравнить только время суток без даты

Типичная задача — отобрать операции, совершённые в рабочие часы, ночную смену или до обеда. Здесь дату нужно отбросить и сравнивать только компоненты времени. В языке запросов для этого есть функции ЧАС(Дата), МИНУТА(Дата) и СЕКУНДА(Дата), возвращающие числа.

ВЫБРАТЬ

Чек.Ссылка КАК Чек,

Чек.Дата КАК ДатаВремя

ИЗ

Документ.ЧекККМ КАК Чек

ГДЕ

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

И (ЧАС(Чек.Дата) >= 22

ИЛИ ЧАС(Чек.Дата) < 6)

Пример выше отбирает чеки ночной смены — с 22:00 до 06:00. Обратите внимание: интервал «через полночь» нельзя выразить одним условием «час между 22 и 6», поэтому используется логическое ИЛИ двух условий.

Если нужно сравнить время с точностью до минут, комбинируйте функции: ЧАС(Дата) 60 + МИНУТА(Дата) >= 8 60 + 30 — условие «не раньше 08:30». Перевод в минуты от полуночи делает сравнение линейным и избавляет от сложных составных условий.

bsl
// Отбор операций до 12:30 независимо от даты
Запрос.Текст =
"ВЫБРАТЬ Операции.Ссылка
|ИЗ Документ.Операция КАК Операции
|ГДЕ ЧАС(Операции.Дата) * 60 + МИНУТА(Операции.Дата) <= 750";

Сравнение с текущим моментом и пустой датой

В языке запросов нет функции «текущая дата» — её нужно передавать параметром из кода. Используйте ТекущаяДатаСеанса(), а не ТекущаяДата(): дата сеанса едина для всего сеанса и согласована с сервером, что важно в клиент-серверном режиме, где часы клиента и сервера могут расходиться.

Для проверки просрочки типичное условие выглядит так: ГДЕ Задача.СрокИсполнения < &ТекущийМомент И НЕ Задача.Выполнена. Параметр &ТекущийМомент устанавливается один раз перед выполнением запроса.

Отдельный случай — проверка на незаполненную дату. Пустая дата в 1С — это 01.01.0001 00:00:00. В запросе её задают через ДАТАВРЕМЯ(1,1,1) или сравнением с параметром, содержащим пустую дату: ГДЕ Документ.ДатаОплаты = ДАТАВРЕМЯ(1,1,1). Проверка ЕСТЬ NULL для дат не подходит — NULL возникает только при соединениях, а незаполненное поле хранит именно «нулевую» дату.

Типичные ошибки при сравнении дат и времени
01
Сравнение Дата = &Дата без времени — выборка пустая, потому что параметр трактуется как 00:00:00
02
Использование МЕЖДУ с границами «начало — начало следующего периода» — граничные записи попадают в оба периода
03
Проверка незаполненной даты через ЕСТЬ NULL вместо ДАТАВРЕМЯ(1,1,1) — условие никогда не срабатывает
04
Передача ТекущаяДата() с клиента — в клиент-серверном режиме возможны расхождения часов, используйте ТекущаяДатаСеанса()
05
Сравнение строкового представления даты вместо значения типа Дата — сортировка и сравнение идут по алфавиту, а не по времени

Разница между двумя датами и сравнение длительностей

Иногда требуется не просто сравнить два момента, а вычислить интервал между ними: сколько часов заказ находился в работе, какова просрочка в днях. Для этого в языке запросов есть функция РАЗНОСТЬДАТ(Дата1, Дата2, Единица), возвращающая число — количество указанных единиц (СЕКУНДА, МИНУТА, ЧАС, ДЕНЬ, МЕСЯЦ и др.) между двумя датами.

ВЫБРАТЬ

Заказ.Ссылка КАК Заказ,

РАЗНОСТЬДАТ(Заказ.Дата, Заказ.ДатаОтгрузки, ЧАС) КАК ЧасовВРаботе

ИЗ

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

ГДЕ

РАЗНОСТЬДАТ(Заказ.Дата, Заказ.ДатаОтгрузки, ДЕНЬ) > 3

Условие в примере отбирает заказы, обработанные дольше трёх дней. Учтите: РАЗНОСТЬДАТ считает целые единицы, поэтому интервал 2 дня 23 часа в единицах ДЕНЬ даст 2. Если нужна точность — считайте в часах или минутах и делите.

Если дата отгрузки может быть не заполнена, результат функции для пустой даты будет некорректным. Добавляйте защитное условие Заказ.ДатаОтгрузки <> ДАТАВРЕМЯ(1,1,1) или подставляйте текущий момент через ВЫБОР КОГДА ... ТОГДА &ТекущийМомент ИНАЧЕ ... КОНЕЦ.

Способы сравнения дат и времени

Операторы >, <, >=, <, =

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

МЕЖДУ ... И ...

Удобен для отбора за период; помните, что обе границы включаются в интервал

НАЧАЛОПЕРИОДА / КОНЕЦПЕРИОДА

Приведение к границам дня, месяца, года; удобно, но функция на поле таблицы замедляет запрос

ЧАС, МИНУТА, СЕКУНДА

Сравнение времени суток без даты; для составных условий переводите время в минуты от полуночи

РАЗНОСТЬДАТ

Вычисление длительности между двумя моментами и сравнение её с порогом

Проверка результата и контрольные точки

После написания запроса проверьте его на граничных значениях — именно там сравнение времени ломается чаще всего. Минимальный набор проверок: запись ровно в 00:00:00 первого дня периода, запись в 23:59:59 последнего дня, запись с незаполненной датой и запись ровно на границе интервала.

Удобно отладить условие в консоли запросов: выполните запрос с тестовыми параметрами и убедитесь, что граничные документы попадают в выборку ровно один раз. Если отчёт стыкует периоды (смены, сутки), суммы по соседним периодам не должны дублировать друг друга.

Контрольные точки

Как проверить корректность сравнения

Запись в 00:00:00 первого дня
Норма

Попадает в выборку

Тревожный признак

Не попадает — граница начала задана неверно

Запись в 23:59:59 последнего дня
Норма

Попадает в период и не дублируется в следующем

Тревожный признак

Потеряна или учтена дважды

Незаполненная дата
Норма

Записи с ДАТАВРЕМЯ(1,1,1) обрабатываются отдельным условием

Тревожный признак

Попадают в выборку как самые ранние или искажают РАЗНОСТЬДАТ

Производительность на большой таблице
Норма

Условие по полю даты без обёртки в функции

Тревожный признак

Функция применяется к полю таблицы — запрос сканирует всё

Частые вопросы

Можно ли сравнить дату со строкой вида «01.03.2026»?

Нет, сравнивать нужно значения типа «Дата». Строку сначала преобразуйте в коде через Дата("20260301") или передайте параметр правильного типа. Сравнение даты со строкой либо даст ошибку, либо приведёт к неочевидному результату из-за неявного преобразования.

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

Приведите обе стороны к началу дня: НАЧАЛОПЕРИОДА(Поле, ДЕНЬ) = НАЧАЛОПЕРИОДА(&Дата, ДЕНЬ). На больших таблицах предпочтительнее интервал Поле >= НАЧАЛОПЕРИОДА(&Дата, ДЕНЬ) И Поле < ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&Дата, ДЕНЬ), ДЕНЬ, 1) — он не мешает использованию индекса.

Как отобрать записи за последние N часов?

Передайте параметр границы из кода: Запрос.УстановитьПараметр("Граница", ТекущаяДатаСеанса() - N * 3600) и условие ГДЕ Таблица.Дата >= &Граница. Либо используйте в запросе ДОБАВИТЬКДАТЕ(&ТекущийМомент, ЧАС, -&N).

Почему МЕЖДУ иногда даёт дубли при стыковке периодов?

Оператор МЕЖДУ включает обе границы. Если один период задан «с 00:00:00 по 23:59:59», а следующий «с 00:00:00 следующего дня», дублей нет, но если границы совпадают (конец одного = начало другого), запись на границе попадёт в оба. Используйте схему «начало включительно, конец исключительно».

Как сравнить время, если оно хранится в отдельном поле типа «Число» или «Строка»?

Такое встречается в старых конфигурациях. Числовое время (например, 930 для 09:30) сравнивайте арифметически. Строковое «ЧЧ:ММ» корректно сравнивается лексикографически только при формате с ведущими нулями, но надёжнее преобразовать его в число минут от полуночи ещё на этапе записи данных.

Что быстрее: МЕЖДУ или пара условий >= и < ?

С точки зрения СУБД оба варианта обычно транслируются в одинаковый план запроса, разницы в скорости практически нет. Выбирайте по смыслу: МЕЖДУ — когда обе границы включительно, пара условий — когда конец интервала исключается.

Итог

Что важно запомнить

Тип «Дата» в 1С всегда содержит время, поэтому равенство почти не используют — вместо него применяют интервалы с границей «начало включительно, конец исключительно». Для времени суток используют ЧАС, МИНУТА, СЕКУНДА, для длительностей — РАЗНОСТЬДАТ, а пустую дату проверяют через ДАТАВРЕМЯ(1,1,1). Условия по полю даты без обёртки в функции работают быстрее за счёт индекса.