Работа с временными метками в системе 1С:Предприятие часто становится камнем преткновения даже для опытных разработчиков. Казалось бы, простая операция сравнения двух дат и времени может привести к непредсказуемым результатам, если не учитывать специфику хранения данных в СУБД. Особенно это критично при построении сложных отчетов или регламентных заданий, где каждая секунда имеет значение.

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

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

Особенности типа данных ДатаВремя в 1С

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

Когда вы формируете условие в запросе, например ГДЕ ДатаРегистрации = &ДатаПараметр, система выполняет побайтовое сравнение. Если в параметре &ДатаПараметр указано время 10:00:00, а в базе запись имеет время 10:00:05, условие не выполнится. Точность сравнения здесь играет решающую роль.

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

⚠️ Внимание: При переносе данных из внешних источников или при использовании ODBC-соединений формат передачи времени может отличаться. Всегда проверяйте, не смещается ли часовой пояс при загрузке, так как это изменит значение поля и нарушит логику сравнения.

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

💡

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

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

Наиболее надежный способ работы со временем — это использование диапазонов вместо поиска точного совпадения. Операторы МЕЖДУ, >= и <= позволяют гибко настраивать выборку. Это особенно актуально для отчетов за период, где пользователю важно видеть все документы, созданные в течение выбранного дня.

При формировании условия "с начала дня по конец дня" разработчики часто забывают, что конец дня в 1С — это 23:59:59. Если документ будет создан в 23:59:59.500 (полсекунды), он может не попасть в выборку, если сравнение идет строго по секундам. Поэтому безопаснее использовать условие "меньше начала следующего дня".

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

ВЫБРАТЬ

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

Документы.Дата

ИЗ

Документ.РеализацияТоваровУслуг КАК Документы

ГДЕ

Документы.Дата >= НАЧАЛОПЕРИОДА(&Период, ДЕНЬ)

И Документы.Дата < КОНЕЦПЕРИОДА(&Период, ДЕНЬ) + 1

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

📊 Какой метод сравнения времени вы используете чаще?
Точное равенство (=)
Диапазон (Между)
Функции начала/конца дня
Сравнение только даты (Без времени)

Работа с пустыми значениями (NULL) во времени

Один из самых коварных аспектов работы с датами — это обработка пустых значений. В SQL-диалекте 1С пустая дата не равна нулю и не равна строке. Попытка сравнить поле, содержащее NULL, с любой датой через оператор равенства вернет ЛОЖЬ.

Если в вашей базе допускаются документы без проставленной даты проведения или регистрации, стандартное условие ГДЕ Дата = &Параметр просто проигнорирует эти записи. Для явного поиска записей с отсутствующим временем необходимо использовать специальный синтаксис.

  • 🔍 Используйте конструкцию ЕСТЬNULL(Дата, ЛОЖЬ) для фильтрации записей, где дата заполнена.
  • 🚫 Избегайте сравнения Дата = NULL, это всегда вернет пустой результат.
  • ✅ Для поиска пустых дат пишите условие Дата ЕСТЬ NULL.

Если вы часто фильтруете отчеты по признаку "проведен/не проведен" или "есть дата/нет даты", убедитесь, что индекс в конфигурации настроен корректно, иначе производительность запроса может упасть в разы.

⚠️ Внимание: В некоторых старых версиях платформы или при работе с внешними базами данных (не родной СУБД 1С) поведение оператора ЕСТЬ NULL может отличаться. Всегда тестируйте логику на тестовой копии базы перед выкладкой на прод.

Также существует функция ЗНАЧЕНИЕ(ТипДатаВремя), которая возвращает пустую дату, но использовать её для сравнения в запросе не рекомендуется из-за возможных проблем с типизацией параметров.

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

Сравнение полей типа ДатаВремя является ресурсоемкой операцией, особенно в больших базах данных с миллионами записей. Неправильно написанное условие может привести к полному сканированию таблицы (Full Table Scan), что заблокирует работу других пользователей.

Главное правило оптимизации: не применяйте функции к полям таблицы в левой части условия сравнения. Если вы напишете ГДЕ ДЕНЬ(Документы.Дата) = 15, оптимизатор запросов не сможет использовать индекс по полю Дата. Вместо этого он будет вычислять день для каждой строки таблицы.

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

Тип условия Использование индекса Влияние на скорость
Дата >= &Начало Да (Полное) Высокая
ГОД(Дата) = 2026 Нет Низкая
Дата = &ТочнаяДата Да (Полное) Высокая
СУММА(ВРЕМЯ(Дата)) > 10 Нет Критически низкая

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

💡

Никогда не оборачивайте поле таблицы в функции (День(), Месяц(), Год()) внутри условия ГДЕ. Это гарантированно отключит использование индексов.

Сравнение времени в условиях группировки

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

Для решения этой задачи используется функция НАЧАЛОПЕРИОДА непосредственно в списке выбираемых полей. Это позволяет "округлить" время события до начала нужного интервала и сгруппировать показатели по этим округленным значениям.

ВЫБРАТЬ

НАЧАЛОПЕРИОДА(Продажи.МоментВремени, ЧАС) КАК ЧасПродажи,

СУММА(Продажи.Сумма) КАК СуммаЗаЧас

ИЗ

РегистрНакопления.Продажи КАК Продажи

ГДЕ

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

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

НАЧАЛОПЕРИОДА(Продажи.МоментВремени, ЧАС)

В данном примере мы агрегируем данные по часам. Обратите внимание, что в условии ГДЕ мы используем исходное поле для точной фильтрации, а в ВЫБРАТЬ и СГРУППИРОВАТЬ ПО — уже преобразованное значение. Это правильный паттерн построения аналитических запросов.

Если вам нужно сравнивать такие сгруппированные периоды между собой (например, найти часы, где продажи были выше средних), лучше вынести расчет начал периодов во временную таблицу. Это упростит основную логику запроса и позволит повторно использовать вычисленные интервалы.

Особенности работы с часовыми поясами

При работе в распределенных базах или с веб-клиентами время может сохраняться в UTC, а отображаться в локальном времени пользователя. Сравнение таких значений без конвертации приведет к сдвигу на количество часов разницы с Гринвичем.

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

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

Всегда используйте параметры запроса с явным указанием типа Дата. Не передавайте даты как строки вида "20.10.2023", так как порядок дня и месяца может быть истолкован неправильно в зависимости от локали сервера (DD.MM.YYYY против MM.DD.YYYY).

  • 🛑 Ошибка: Сравнение даты с числом (например, таймстампом Unix). Требуется явное преобразование.
  • 🛑 Ошибка: Игнорирование летнего/зимнего времени при сравнении архивных данных.
  • 🛑 Ошибка: Использование ТЕКУЩАЯДАТА() внутри текста запроса вместо параметра. Это делает план выполнения запроса нестабильным.

Еще один нюанс связан с високосными годами. Функции работы с периодами в 1С обычно учитывают это автоматически, но если вы рассчитываете даты вручную (прибавляя 365 дней), вы получите ошибку в один день раз в четыре года.

⚠️ Внимание: Интерфейс и возможности конструктора запросов могут обновляться с новыми версиями платформы 1С. Если вы используете очень старую версию (ниже 8.3.10), некоторые функции работы с периодами могут быть недоступны или работать медленнее. Рекомендуется сверяться с синтаксис-помощником вашей конкретной версии.

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

☑️ Чек-лист проверки запроса со временем

Выполнено: 0 / 5
Почему запрос не находит документ, хотя дата визуально совпадает?

Скорее всего, различаются секунды или миллисекунды, которые не видны в обычном поле формы. Визуально 10:00 и 10:00:05 выглядят одинаково, если не включен расширенный формат. Используйте отладчик, чтобы посмотреть точное значение поля в базе данных.

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

Используйте функцию НАЧАЛОДНЯ(Дата) для обоих сравниваемых значений. Это обрежет время до 00:00:00, и сравнение пройдет корректно по календарным суткам.

Можно ли использовать оператор LIKE для дат в 1С?

Технически можно, приведя дату к строке, но это крайне плохая практика. Она отключает индексы и работает медленно. Используйте диапазоны МЕЖДУ или функции начала/конца периода.

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

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

Влияет ли формат даты в конфигураторе на сравнение в запросе?

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