Работа с временными интервалами в платформе 1С:Предприятие является одной из самых частых задач при разработке отчетов и обработок данных. Разработчики часто сталкиваются с необходимостью выбрать все документы или регистры, относящиеся к конкретному календарному дню. На первый взгляд, задача кажется простой, но особенности хранения даты и времени в SQL-серверах требуют особого подхода к формированию условий выборки.
Если просто приравнить поле даты к конкретной дате, система может пропустить важные записи из-за наличия временной составляющей. Например, запись с датой 01.01.2026 12:30:00 не попадет в выборку, если вы ищете просто 01.01.2026 без учета времени. Понимание того, как платформа интерпретирует границы периода, становится критически важным для корректной работы вашего кода.
В этой статье мы детально разберем, как правильно реализовать условие «дата как день» в языке запросов 1С. Мы рассмотрим встроенные функции работы с датами, типичные ошибки при написании условий и способы оптимизации таких запросов для ускорения выполнения.
Особенности хранения даты и времени в 1С
В системе 1С:Предприятие тип данных Дата хранится с точностью до секунды. Это означает, что любое значение даты всегда включает в себя временную компоненту. Даже если пользователь в интерфейсе выбрал только день, во внутренней структуре данных время по умолчанию устанавливается в ноль часов, ноль минут и ноль секунд.
Однако при записи документов в базу данных время часто фиксируется фактически в момент проведения. Это создает ситуацию, когда в одном дне могут находиться записи с разным временем: от 00:00:01 до 23:59:59. При формировании запроса необходимо учитывать весь этот диапазон, чтобы выборка была полной.
Использование простого сравнения Где Дата = &Дата является грубой ошибкой в большинстве случаев. Такое условие сработает только для тех записей, где время строго равно 00:00:00. Все остальные документы, проведенные в течение дня, будут исключены из результата, что приведет к некорректным данным в отчетах.
⚠️ Внимание: При работе с серверами баз данных, отличными от файловых вариантов 1С, игнорирование временной части может приводить к существенному расхождению данных между интерфейсом программы и результатами выборки.
Для корректной работы необходимо использовать диапазон значений. Вам нужно определить начало суток и конец суток для интересующей вас даты. Именно в этом промежутке находятся все события, произошедшие в течение конкретного календарного дня.
Функции НАЧАЛОПЕРИОДА и КОНЕЦПЕРИОДА
Платформа 1С предоставляет мощный инструментарий для манипуляций с датами непосредственно на уровне языка запросов. Две ключевые функции — НАЧАЛОПЕРИОДА и КОНЕЦПЕРИОДА — позволяют автоматически вычислять границы временных интервалов различной granularity (гранулярности).
Функция НАЧАЛОПЕРИОДА(Дата, Период) возвращает дату начала указанного периода. Если в качестве периода указать День, функция обрежет время до 00:00:00 выбранного дня. Это идеальная точка отсчета для нижней границы вашего диапазона.
Функция КОНЕЦПЕРИОДА(Дата, Период) работает аналогично, но возвращает последнюю возможную дату и время внутри периода. Для дня это будет 23:59:59. Использование этих функций делает код запроса универсальным и независимым от ручного расчета времени.
- 📅 Функция
НАЧАЛОПЕРИОДА(&Дата, День)гарантирует получение начала суток (00:00:00). - ⏰ Функция
КОНЕЦПЕРИОДА(&Дата, День)автоматически рассчитывает конец суток (23:59:59). - 🔄 Эти функции работают на стороне сервера баз данных, что обеспечивает высокую производительность выборки.
Применение этих функций в условии ГДЕ позволяет создать замкнутый интервал. Запрос будет выглядеть логично и понятно для любого разработчика, читающего ваш код. Это повышает поддерживаемость конфигурации в будущем.
Используйте константу периода «День» в функциях работы с датами, чтобы код оставался читаемым и не требовал магических чисел для расчета секунд в сутках.
Синтаксис условия выборки за день
Правильная запись условия выборки — залог успеха. В языке запросов 1С диапазон значений задается через операторы Между или через комбинацию >= и <=. Оба подхода допустимы, но имеют свои нюансы восприятия.
Вариант с использованием оператора Между является наиболее компактным. Он явно указывает, что нас интересует весь промежуток от начала до конца. Синтаксис требует указания нижней и верхней границы, которые мы получаем с помощью функций периода.
ВЫБРАТЬ
Документ.Ссылка,
Документ.Дата
ИЗ
Документ.РеализацияТоваровУслуг КАК Документ
ГДЕ
Документ.Дата МЕЖДУ НАЧАЛОПЕРИОДА(&Дата, День)
И КОНЕЦПЕРИОДА(&Дата, День)
Альтернативный вариант с использованием сравнений может быть полезен, если вам нужно исключить одну из границ диапазона (например, получить интервал полуоткрытым). Однако для задачи «выбрать все за день» оператор МЕЖДУ подходит идеально.
☑️ Проверка корректности запроса
Обратите внимание на параметр &Дата. В кодировке 1С параметры запроса передаются из внешней обработки или формы. Важно, чтобы в этот параметр передавалось значение типа Дата, а не Строка, чтобы функции сработали корректно.
Сравнение методов: Начало/Конец суток vs Между
Существует несколько подходов к реализации одной и той же логики. Разработчики часто спорят о том, какой метод лучше: использовать встроенные функции периода или вычислять границы вручную. Давайте сравним эти подходы в таблице.
| Метод | Читаемость кода | Производительность | Риск ошибки |
|---|---|---|---|
НАЧАЛОПЕРИОДА / КОНЕЦПЕРИОДА |
Высокая | Оптимальная | Минимальный |
Ручной расчет (+ 86399 секунд) |
Низкая | Оптимальная | Высокий |
| Приведение к типу Дата (без времени) | Средняя | Средняя | Средний |
Использование СТРОКА для даты |
Низкая | Низкая | Критический |
Использование ручного расчета секунд (добавление 86399 секунд к началу дня) хотя и работает, но делает код менее понятным. Коллега, поддерживающий вашу конфигурацию, может не сразу понять, что означает это число.
Функции платформы являются предпочтительным выбором. Они самодокументируемы: название функции сразу говорит о намерении разработчика. Кроме того, платформа сама оптимизирует вызов этих функций при трансляции запроса в SQL.
Всегда отдавайте предпочтение встроенным функциям работы с периодами вместо ручных арифметических операций с секундами — это стандарт разработки в экосистеме 1С.
Оптимизация запросов с использованием индексов
При выборке больших массивов данных критически важным становится использование индексов. Если таблица документа содержит миллионы записей, простой перебор всех строк для проверки условия даты займет недопустимо много времени.
Платформа 1С автоматически создает индексы по полям, используемым в условиях отбора, если это предусмотрено конфигурацией. Однако разработчик должен убедиться, что условие в запросе позволяет двигателю базы данных использовать этот индекс.
Использование функций от поля даты в условии ГДЕ (например, ГОД(Дата) = 2026) часто приводит к тому, что индекс не используется. Это называется «несистемным» использованием индекса. В нашем случае мы применяем функции к параметру, а не к полю таблицы, что является правильным подходом.
- 🚀 Условие
Поле >= Значениепозволяет использовать индекс по полю даты. - ⛔ Избегайте обертывания поля таблицы в функции, например
НАЧАЛОПЕРИОДА(Поле, День)в условии. - ✅ Применяйте функции только к параметрам запроса или константам.
Если вы заметили, что запрос выполняется медленно, проверьте план выполнения. Убедитесь, что СУБД использует индекс по дате документа для ограничения количества сканируемых записей.
⚠️ Внимание: Нагрузка на сервер 1С и сервер баз данных может критически возрасти, если запросы с датами не используют индексы. Всегда тестируйте производительность на объемах данных, близких к боевым.
Что такое несистемное использование индекса?
Несистемное использование индекса возникает, когда условие запроса требует предварительного вычисления значения для каждой строки таблицы перед сравнением. В этом случае база данных вынуждена сканировать всю таблицю (Full Table Scan), игнорируя существующие индексы, что резко снижает скорость работы.
Типичные ошибки и способы их устранения
Даже опытные разработчики допускают ошибки при работе с временными интервалами. Одна из самых распространенных проблем — «потеря» последнего часа или секунды дня из-за неправильного понимания работы функции КОНЕЦПЕРИОДА.
Некоторые разработчики пытаются использовать строгое неравенство < для верхней границы, подставляя начало следующего дня. Это тоже рабочий метод, но он требует аккуратности. Ошибка в расчете следующего дня (особенно при переходе через месяц или год) приведет к потере данных.
Еще одна частая ошибка связана с часовыми поясами. Если сервер 1С и клиент находятся в разных часовых поясах, а в настройках системы не учтена конвертация времени, данные могут смещаться. В большинстве локальных задач это не критично, но для распределенных систем это важно.
Всегда проверяйте тип передаваемого параметра. Если в параметр &Дата случайно попадет пустое значение или значение другого типа, выполнение запроса прервется с ошибкой. Используйте предварительную проверку в коде обработки перед запуском запроса.
Для отладки таких запросов удобно выводить сформированный текст запроса в консоль или файл. Это позволяет увидеть реальные значения, которые подставились вместо параметров, и убедиться в корректности границ интервала.
Часто задаваемые вопросы (FAQ)
Можно ли использовать функцию ОКРУГЛИТЬ для получения даты как дня?
Использовать функцию ОКРУГЛИТЬ для этой задачи не рекомендуется. Она предназначена для математического округления чисел и может работать некорректно с датами в контексте SQL-запросов, а также не гарантирует получение строго начала или конца периода.
Как выбрать данные за вчерашний день динамически?
Для этого нужно передать в параметр запроса дату, полученную выражением ТЕКУЩАЯДАТА() - 1. Функции НАЧАЛОПЕРИОДА и КОНЕЦПЕРИОДА корректно обработают это значение и выстроят нужный интервал.
Влияет ли високосный год на работу функции КОНЕЦПЕРИОДА?
Нет, не влияет. Функция КОНЕЦПЕРИОДА знает календарные правила и автоматически корректно определяет количество дней в феврале (28 или 29), а также длину других месяцев. Вам не нужно писать дополнительную логику для високосных лет.
Что делать, если нужно выбрать данные за месяц, а не за день?
Логика остается той же. Просто измените второй параметр в функциях периода с День на Месяц. Запрос ГДЕ Дата МЕЖДУ НАЧАЛОПЕРИОДА(&Дата, Месяц) И КОНЕЦПЕРИОДА(&Дата, Месяц) выберет все записи за указанный месяц.
Почему запрос работает медленно на больших базах?
Вероятнее всего, не используется индекс по дате. Проверьте, не оборачиваете ли вы поле таблицы в функции внутри условия ГДЕ. Также убедитесь, что в конфигурации для соответствующего регистра или документа установлен индекс по дате.