Работа с типом данных Дата в системе 1С:Предприятие часто вызывает вопросы у разработчиков, особенно когда требуется игнорировать временную составляющую. Внутренне дата хранится как количество секунд, прошедших с начала эры, поэтому значение 01.01.2023 15:30:00 технически отличается от 01.01.2023 00:00:00. Эта разница критична при группировках, соединениях таблиц или формировании отчетов, где важна только календарная дата.
Частая ошибка заключается в попытке просто вывести поле даты в макет или отчет, надеясь на автоматическое форматирование. Однако для корректной логики выборки, например, при использовании оператора В ГРАНИЦАХ или при группировке по суткам, необходимо явно преобразовать значение. Существует несколько штатных методов решения этой задачи непосредственно внутри текста запроса, каждый из которых имеет свои особенности производительности и читаемости кода.
В данной статье мы разберем основные функции языка запросов, позволяющие отсечь время, сравним их эффективность и рассмотрим нюансы, связанные с настройками сеанса и региональными стандартами. Понимание этих механизмов позволит писать более оптимальный код и избегать распространенных ловушек при работе с временными интервалами.
Использование функции НачалаДня для обрезки времени
Самым распространенным и рекомендуемым способом получения даты без времени является использование встроенной функции НачалаДня. Эта функция принимает значение даты и возвращает новую дату, у которой время установлено ровно на 00:00:00. Это стандартный подход, который обеспечивает наилучшую читаемость кода для других разработчиков.
При использовании НачалаДня(Дата) в условии отбора или в списке полей, система автоматически выполняет преобразование. Это делает её предпочтительнее по сравнению с обработкой данных на стороне клиента.
Рассмотрим пример использования в контексте выборки документов за конкретный день. Если вы передали в параметр дату с временем, функция гарантированно приведет диапазон к началу суток.
ВЫБРАТЬ
ДокументРасход.Ссылка,
ДокументРасход.Дата,
НачалаДня(ДокументРасход.Дата) КАК ДатаБезВремени
ИЗ
Документ.РеализацияТоваровУслуг КАК ДокументРасход
ГДЕ
НачалаДня(ДокументРасход.Дата) = &ДатаОтчета
Однако стоит учитывать один нюанс: использование функций в условии ГДЕ может в некоторых редких случаях (зависящих от конкретной СУБД и версии платформы) препятствовать использованию индексов по полю даты. Хотя оптимизатор 1С обычно справляется с этим хорошо, для максимального быстродействия на огромных объемах данных иногда лучше формировать границы интервала явно.
Используйте НачалаДня() для группировки в списке выборки — это гарантирует, что строки с разным временем, но одной датой, попадут в одну группу.
Функция Округлить и её применение к датам
Альтернативой функции начала дня является более универсальная функция Округлить. Она позволяет округлять дату до заданной точности, которая передается вторым параметром. Для получения даты без времени необходимо использовать перечисление Период.День.
Синтаксис выглядит следующим образом: Округлить(Дата, Период.День). Результат работы этой функции аналогичен НачалаДня, если время исходной даты меньше 12 часов. Однако, если время больше полудня, функция может округлить дату до следующего дня, что часто является нежелательным поведением при фильтрации.
- 🕒 Функция
Округлитьматематически округляет значение, а не просто обрезает дробную часть. - 📅 Для точного получения начала суток лучше использовать
НачалаДняилиОкруглитьВниз. - ⚙️ Параметр точности может принимать значения:
Секунда,Минута,Час,День,Месяц,Квартал,Год.
Если ваша задача — именно "отбросить" время, а не округлить его, использование Округлить с параметром День может привести к логическим ошибкам. Например, документ, созданный в 14:00, будет отнесен к завтрашнему дню. Поэтому данный метод подходит скорее для аналитических расчетов, где допустима погрешность, но не для строгой фильтрации по регистрам.
⚠️ Внимание: Никогда не используйте обычное математическое округление для фильтрации документов по датам, если не уверены в поведении функции при времени после 12:00. Это может исключить часть документов из выборки или включить лишние.
Настройка форматной строки для вывода данных
Иногда нет необходимости изменять само значение даты в запросе, а нужно лишь корректно отобразить его в отчете или печатной форме. В этом случае преобразование выполняется на этапе форматирования вывода с использованием функции Формат или настроек макета.
В языке запросов 1С можно сразу применить форматирование к полю, используя конструкцию КАК с указанием строки формата. Это позволяет передать в макет уже подготовленную строку или специальное представление, где время не отображается.
Ключевым моментом здесь является использование описания формата ДФ="dd.MM.yyyy". Такой формат игнорирует часовую и минутную составляющие при генерации строкового представления. Однако стоит помнить, что тип данных останется Дата, просто изменится способ его отображения в некоторых контекстах.
ВЫБРАТЬ
Формат(ДокументПриход.Дата, "ДФ=dd.MM.yyyy") КАК ДатаСтрока
ИЗ
Документ.ПоступлениеТоваровУслуг КАК ДокументПриход
Такой подход полезен при выгрузке данных в текстовые файлы или при формировании простых списков для пользователя. Но для последующих вычислений или сравнений внутри запроса этот метод не подходит, так как результат часто приводится к строковому типу, что меняет логику работы оператора СОРТИРОВКА ПО.
Особенности региональных настроек
Формат "ДФ" зависит от настроек локали пользователя. В некоторых случаях разделитель точек может заменяться на слэши, если это задано в региональных стандартах ОС.
Сравнение производительности методов обрезки
Выбор между различными методами удаления времени может повлиять на скорость выполнения запроса, особенно на больших информационных базах под управлением MS SQL Server или PostgreSQL. Разница обусловлена тем, как именно функция транслируется в диалект SQL целевой СУБД.
Функция НачалаДня обычно транслируется в эффективные операции работы с типом datetime или date на стороне сервера баз данных. Это позволяет использовать индексы, если условие построено корректно. В то же время, сложные вычисления с приведением типов могут вынудить сервер выполнять полный скан таблицы.
Ниже приведена таблица, сравнивающая основные характеристики методов:
| Метод | Читаемость | Производительность | Безопасность типа |
|---|---|---|---|
| НачалаДня() | Высокая | Высокая | Дата |
| Округлить(.., День) | Средняя | Средняя | Дата |
| Формат(.., "ДФ=..") | Низкая | Низкая (строка) | Строка |
| Ручной расчет (ВРЕМЯ) | Низкая | Низкая | Число |
Как видно из сравнения, использование специализированной функции НачалаДня является золотой серединой. Она обеспечивает высокий уровень абстракции, понятный программисту 1С, и при этом позволяет оптимизатору запросов строить эффективные планы выполнения.
Для производственных баз данных с миллионами записей всегда отдавайте предпочтение функциям, которые не преобразуют тип Дата в Строку внутри условия отбора.
Работа с интервалами и оператором В ГРАНИЦАХ
Часто задача "получить дату без времени" возникает не для отображения, а для фильтрации данных за полный день. В этом случае использование функций в условии ГДЕ может быть избыточным. Более элегантным решением является правильное формирование параметров запроса.
Оператор В ГРАНИЦАХ автоматически учитывает время. Если вы передаете в параметр дату 25.10.2023 (без времени, то есть 00:00:00), то условие ГДЕ Дата В ГРАНИЦАХ (&ДатаНач, &ДатаКон) сработает корректно только если вы явно укажете конец дня.
Рекомендуемый паттерн для выборки за день выглядит так:
- 🔹 Параметр начала:
НачалаДня(&Период) - 🔹 Параметр конца:
КонцаДня(&Период) - 🔹 Условие:
ГДЕ Дата В ГРАНИЦАХ (&Нач, &Кон)
Такой подход позволяет избежать вызова функций для каждой строки таблицы в условии отбора. Движок 1С сможет использовать индекс по полю даты максимально эффективно, так как сравниваются конкретные константные значения границ.
⚠️ Внимание: При работе с временными зонами убедитесь, что функции
НачалаДняиКонцаДняприменяются с учетом смещения времени сеанса, иначе могут возникнуть расхождения при выгрузке данных в другие часовые пояса.
ℹ️ Интерфейс и функционал платформы 1С регулярно обновляется. Поведение оптимизатора запросов может изменяться в новых релизах. Всегда проверяйте план выполнения запроса в режиме отладки для критически важных отчетов.
☑️ Проверка корректности выборки за день
Частые ошибки и решение проблем с типами
Одной из самых распространенных проблем является попытка сравнить дату с временем и дату без времени через оператор равенства =. Например, если в базе документ проведен в 10:15:00, а вы ищете Дата = &ДатаПараметр, где параметр равен началу дня, запись не будет найдена.
Вторая ошибка связана с типизацией параметров. Если в запросе поле имеет тип Дата, а параметр передается как Строка с форматом "ДД.ММ.ГГГГ", может произойти неявное преобразование, которое зависит от настроек локали. Это приводит к нестабильной работе кода на разных компьютерах пользователей.
Для избежания ошибок всегда явно приводите типы данных. Используйте конструкцию ЕСТЬNULL или проверяйте заполненность параметров перед выполнением запроса. Также не забывайте про високосные годы и переходы на летнее время, хотя функция НачалаДня обычно корректно обрабатывает эти случаи.
Если вы столкнулись с ситуацией, когда время "не обрезается", проверьте, не используется ли в запросе соединение (ЛЕВОЕ СОЕДИНЕНИЕ), где условие на дату вынесено в блок ПО. В таких случаях логика выполнения может отличаться от ожидаемой.
Почему не работает сравнение строк?
Сравнение строки "01.01.2023" и даты 01.01.2023 00:00:00 невозможно напрямую. Необходимо либо привести оба значения к дате, либо оба к строке одинакового формата.
Можно ли обрезать время через арифметические операции?
Технически можно вычесть время из даты, используя функцию ВРЕМЯ, но это плохая практика. Например: Дата - ВРЕМЯ(ЧАС(Дата), МИНУТА(Дата), СЕКУНДА(Дата)). Такой код трудно читать, и он работает медленнее, чем встроенная функция НачалаДня.
Влияет ли обрезка времени на работу с регистрами накопления?
Да, влияет критически. Регистры накопления часто имеют измерения типа Дата. Если вы группируете остатки по НачалаДня(Период), вы получите корректные срезы на конец дня. Если игнорировать время, данные могут разбиться по разным записям регистра.
Как получить только время без даты в запросе 1С?
Для получения только времени используйте функцию ВРЕМЯ(Дата). Она вернет значение типа Время, которое можно форматировать отдельно. Это обратная операция к получению даты без времени.
Почему в макете отображается время, хотя в запросе использовано НачалаДня?
Функция НачалаДня возвращает дату с временем 00:00:00. Если в макете (табличном документе) не задан формат ячейки, система может показать нулевое время явно. Необходимо настроить формат ячейки макета на "ДД.ММ.ГГГГ".