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

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

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

Функции начала и конца дня для нормализации даты

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

Когда вы применяете эту функцию в секции ГДЕ, сервер 1С автоматически оптимизирует запрос, если это возможно, но важно понимать разницу между вычислением значения в условии и вычислением в списке выборки. Для группировки документов по суткам функция НачалоДня(ДатаДокумента) является стандартом де-факто. Она гарантирует, что все записи, созданные в течение одного календарного дня, попадут в одну группу независимо от минуты создания.

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

⚠️ Внимание: Использование функции КонецДня() в условии «Меньше или равно» может привести к потере записей, созданных в последние миллисекунды суток, из-за особенностей округления. Лучше использовать строгое неравенство с началом следующего дня.

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

ВЫБРАТЬ

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

ДокументРеализация.Дата КАК Дата

ИЗ

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

ГДЕ

ДокументРеализация.Дата >= &НачалоПериода

И ДокументРеализация.Дата < &КонецПериода

Здесь параметры &НачалоПериода и &КонецПериода должны быть рассчитаны в коде на стороне клиента или в СКД как НачалоДня(Параметр) и НачалоДня(Параметр) + 1. Такой подход является наиболее производительным.

💡

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

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

Функция ОКРУГЛИТЬ() предоставляет более гибкий инструмент для работы со временем, позволяя отсекать не только часы, но и минуты или секунды. Синтаксис функции требует указания режима округления, что делает её мощным, но потенциально опасным инструментом в неумелых руках. Для получения даты без времени используется режим округления до дня.

В отличие от НачалоДня, которая всегда возвращает 00:00:00, функция ОКРУГЛИТЬ работает по математическим правилам. Если время документа 13:00, округление до дня даст начало этого же дня. Если же время 12:00 (или близкое к середине суток в других режимах), результат может быть непредсказуемым для новичка, если не указан правильный параметр направления округления.

Для задачи «вывести дату без времени» в списке выборки часто используют конструкцию с явным указанием режима. Это полезно, когда нужно сгруппировать данные не строго по календарным суткам, а, например, по 12-часовым интервалам, хотя для чистой даты это избыточно. Основное применение ОКРУГЛИТЬ в контексте времени — это работа с минутами.

  • 🕒 Режим ВРЕМЯ позволяет оставить только время, отбросив дату.
  • 📅 Режим ДЕНЬ округляет дату до ближайшего начала или конца дня в зависимости от аргумента.
  • ⏱ Режим МИНУТА удобен для группировки событий с точностью до минуты, игнорируя секунды.
  • 🔢 Числовой режим позволяет округлять до десятков или сотен, что редко применяется к датам.

Важно отметить, что использование ОКРУГЛИТЬ в условиях отбора по полям, входящим в ключи индексации, может привести к полному сканированию таблицы. Платформа не всегда может «заглянуть» внутрь функции и понять, что можно использовать индекс. Поэтому для фильтрации лучше использовать диапазон значений, а функцию оставить для формирования итогового поля в списке ВЫБРАТЬ.

Технические детали округления

Внутренне 1С хранит дату как количество секунд, прошедших с начала эры (0001-01-01). Функция округления работает именно с этим числовым представлением, отбрасывая младшие разряды, соответствующие времени.

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

Частая ошибка при выборке данных заключается в попытке сравнить дату с временем с датой без времени через оператор «Равно». Поскольку в базе данных время редко бывает ровно 00:00:00, такое условие почти всегда вернет пустой результат. Правильный подход — использование интервалов.

Когда вы формируете отчет за «Вчера», вы не можете просто написать ГДЕ Дата = &Вчера. Вам необходимо определить диапазон: от начала вчерашнего дня включительно до начала сегодняшнего дня исключительно. Это классическая схема [Begin, End), которая гарантирует, что все документы, созданные в любой момент вчерашних суток, будут выбраны.

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

Метод сравнения Производительность Читаемость Риск ошибок
Прямое равенство (Дата = Параметр) Высокая Высокая Критический (не найдет записи)
Диапазон (>= Начало И < Конец) Высокая Средняя Низкий
Функция в условии (НачалоДня(Дата) = ...) Средняя/Низкая Высокая Средний (проблемы с индексами)
Преобразование в строку Низкая Низкая Высокий (зависит от локали)

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

📊 Какой метод отсечения времени вы используете чаще всего?
Функция НачалоДня()
Диапазон дат (от и до)
Округление
Преобразование в строку

Группировка по датам в консоли запросов и СКД

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

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

Особенность СКД заключается в том, что она может автоматически применять группировку по периоду (День, Неделя, Месяц) через механизм периодов. В этом случае разработчику не нужно вручную прописывать функции в запросе, достаточно настроить группировку в схеме компоновки. Это упрощает поддержку кода, но иногда ограничивает гибкость при сложных вычислениях.

Если же вы используете консоль запросов для быстрой аналитики, привычка писать НАЧАЛОДНЯ(Дата) должна быть доведена до автоматизма. Это спасает от необходимости потом вручную фильтровать дубликаты в Excel. Также обратите внимание на заголовки колонок: без явного указания КАК ДатаБезВремени заголовок будет выглядеть как формула, что неудобно для пользователя.

⚠️ Внимание: При экспорте результатов запроса в табличный документ или Excel, тип данных «Дата» с нулевым временем может все равно отображаться с форматом времени (0:00:00). Это решается настройкой формата ячейки, а не изменением запроса.

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

В распределенных информационных базах и облачных решениях критически важно различать время клиента и время сервера. Функции работы с датой в запросе выполняются на стороне сервера базы данных. Это значит, что НачалоДня(СЕГОДНЯ()) вернет начало дня по серверному времени, которое может отличаться от времени пользователя.

Если ваш сотрудник работает из другого часового пояса, документы, созданные им поздно вечером по его времени, могут попасть в «завтрашний» день по времени сервера. При выборке данных «за сегодня» по серверному времени эти документы могут потеряться или, наоборот, появиться лишние. Для решения этой проблемы существуют функции ЛОКАЛЬНОЕВРЕМЯ() и ВРЕМЯСЕРАВЕРА().

При конвертации времени важно использовать функцию ПРЕОБРАЗОВАТЬВЛОКАЛЬНОЕВРЕМЯ или аналогичные механизмы, если логика бизнеса привязана к местному времени пользователя. Однако в запросах 1С прямая поддержка конвертации часовых поясов внутри SQL-подобного синтаксиса ограничена. Чаще всего эту логику выносят в код на языке 1С перед формированием запроса.

Игнорирование этого фактора приводит к классической ошибке «отчет не сходится». Бухгалтер видит одни цифры, а системное время базы данных говорит о другом. Всегда уточняйте, в каком часовом поясе развернут ваш сервер 1С:Предприятие, особенно если он находится в другом регионе или дата-центре.

💡

Серверный запрос «не знает» о часовом поясе пользователя. Все вычисления дат происходят относительно времени сервера СУБД, если не выполнена явная конвертация.

Альтернативные методы и преобразование типов

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

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

Еще один метод — вычитание времени. Поскольку время хранится как доля суток или секунды, можно теоретически вычесть текущее время из даты. Но это «грязный» хак, который делает код непонятным для других разработчиков и может работать нестабильно на разных версиях платформы. Использование встроенных функций НачалоДня всегда предпочтительнее.

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

  • 🚫 Избегайте преобразования даты в строку для фильтрации — это убивает производительность.
  • ✅ Используйте типизированные поля даты для корректной сортировки и индексации.
  • ⚙️ Проверяйте настройки региональных стандартов сервера, они влияют на формат по умолчанию.

Помните, что код читается чаще, чем пишется. Выбор очевидного и стандартного метода работы с датами сэкономит время вам и вашим коллегам при отладке и доработке конфигурации в будущем.

Можно ли использовать функцию НачалоДня в условии ГДЕ без потери производительности?

В большинстве современных версий платформы 1С:Предприятие 8.3 оптимизатор запросов умеет преобразовывать условия с функциями НачалоДня/КонецДня в диапазоны, что позволяет использовать индексы. Однако гарантировать это на 100% для всех случаев нельзя. Самый надежный способ — явно передавать в запрос параметры начала и конца периода, рассчитанные в коде.

Почему при группировке по дате появляются дубликаты с разным временем?

Это происходит, если в секции СГРУППИРОВАТЬ ПО вы указали исходное поле «Дата», а не выражение «НАЧАЛОДНЯ(Дата)». Система группирует по уникальным значениям поля, и так как время разное, строки не объединяются. Нужно сгруппировать по результату функции.

Как отобразить дату без времени в печатной форме, если в запросе она с временем?

Лучше всего обрезать время на уровне запроса или СКД, чтобы в макет попадала уже очищенная дата. Если это невозможно, настройте формат ячейки в табличном документе или макете печати, указав формат «ДЛФ=КД» (Краткая Дата), который скрывает время визуально.

Влияет ли смена часового пояса сервера на работу функции НачалоДня?

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

Есть ли разница между НачалоДня и Округлить(Дата, РежимОкругления.День)?

Да, есть. НачалоДня всегда возвращает 00:00:00 текущего дня. Округлить может вернуть начало следующего дня, если время ближе к нему (в зависимости от реализации и параметров), или работать менее предсказуемо. Для задачи «отсечь время» НачалоДня является специализированным и безопасным инструментом.