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

Если вы просто попытаетесь сравнить дату документа с датой, введенной пользователем в форму отбора, результат может быть нулевым из-за разницы в часах и минутах. Например, поиск по дате 10.10.2023 00:00:00 не найдет документ, созданный в 10.10.2023 14:30:00. Для корректной работы необходимо «обнулить» время, оставив только число, месяц и год.

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

Основы типа ДатаВремя в платформе 1С

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

Однако для пользователя и логики бизнес-процессов часто требуется работать с дискретными периодами. Когда бухгалтер говорит «отчет за 1-е число», он подразумевает период с 00:00:00 до 23:59:59. Система же видит конкретную точку на временной шкале. Именно поэтому разделение даты и времени становится базовой операцией при формировании выборок.

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

⚠️ Внимание: Прямое приведение типа ДатаВремя к типу Дата (если бы такое было возможно простым кастом) не является штатным способом. Всегда используйте специальные функции платформы для гарантии корректности.

📊 Как вы чаще всего решаете задачу очистки времени?
Через функцию НачалоДня
В цикле перебором
На стороне SQL сервера
Использую готовые обработки

Использование функций в языке запросов

Язык запросов 1С обладает мощным набором встроенных функций для манипуляции временными метками. Наиболее эффективный способ отделить дату от времени — использование функций НАЧАЛОДНЯ() и КОНЕЦДНЯ(). Эти функции выполняются непосредственно на стороне сервера баз данных, что существенно повышает производительность выборки.

Функция НАЧАЛОДНЯ принимает значение типа ДатаВремя и возвращает новую дату, у которой время установлено в 00:00:00. Это идеальный инструмент для группировки данных по суткам. В то же время, КОНЕЦДНЯ устанавливает время на 23:59:59, что удобно для построения интервалов «с... по...».

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

ВЫБРАТЬ

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

НАЧАЛОДНЯ(Документы.РеализацияТоваровУслуг.Дата) КАК ДатаБезВремени

ИЗ

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

ГДЕ

НАЧАЛОДНЯ(Документы.РеализацияТоваровУслуг.Дата) = &ДатаОтбора

В данном примере параметр &ДатаОтбора также должен быть предварительно очищен от времени на стороне клиента или в коде перед запуском запроса. Использование этих функций в условии ГДЕ позволяет эффективно использовать индексы, если они настроены корректно, хотя в некоторых случаях СУБД может потребовать полный скан таблицы.

💡

Для повышения скорости работы запроса старайтесь не оборачивать поле даты в функции внутри условия ГДЕ, если объем данных огромен. Лучше сформировать интервал: ГДЕ Дата >= &Начало И Дата <= &Конец.

Программная обработка в встроенном языке

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

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

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

ИсходнаяДата = ТекущаяДата(); // Например, 25.10.2023 15:45:10

ДатаБезВремени = НачалоДня(ИсходнаяДата); // Результат: 25.10.2023 00:00:00

Сообщить("Очищенная дата: " + ДатаБезВремени);

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

  • 📅 Используйте НачалоДня() для нормализации даты перед записью в регистр.
  • ⏱ Применяйте КонецДня() при формировании отчетов «на конец дня».
  • 🔄 Функция СмещениеДаты() полезна для получения вчерашней или завтрашней даты с обнуленным временем.

Формирование интервалов для отборов

Один из самых надежных способов отфильтровать данные за конкретную дату, не используя преобразование типов в условии — это формирование явного интервала. Метод «от начала дня до конца дня» является наиболее понятным для чтения кода и предсказуемым для оптимизатора запросов.

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

Алгоритм действий программиста выглядит так:

1. Получить дату от пользователя.

2. Вычислить начало дня этой даты.

3. Вычислить начало следующего дня.

4. Использовать условие: ГДЕ Дата >= Начало И Дата < КонецСледующегоДня.

Использование строгого неравенства (<) для правой границы часто предпочтительнее, чем <= КонецДня, так как это исключает любые проблемы с точностью представления времени в разных СУБД (например, если в базе хранятся миллисекунды).

☑️ Алгоритм построения временного интервала

Выполнено: 0 / 4

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

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

Ниже приведена сравнительная таблица основных подходов к обработке временных меток в выборках:

Метод Где выполняется Влияние на индексы Рекомендация
Функция НАЧАЛОДНЯ() в WHERE СУБД Частичное (зависит от СУБД) Хорошо для средних объемов
Интервал (>= и <) СУБД Полное использование индекса Лучший вариант для больших данных
Обработка в цикле 1С Сервер 1С Не используется Только для малых выборок

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

💡

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

Типичные ошибки и нюансы реализации

Несмотря на простоту функций, разработчики часто допускают ошибки, связанные с часовыми поясами и летним временем. Платформа 1С хранит время в UTC (всемирное координированное время) или в локальном времени сервера в зависимости от настроек кластера, что может сдвигать «начало дня» при неправильной интерпретации.

Еще одна распространенная проблема возникает при работе с веб-клиентом и толстым клиентом одновременно. Разница в часовых поясах клиентов может привести к тому, что «сегодня» для одного пользователя будет «вчера» для другого, если не учитывать смещение при формировании отборов.

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

⚠️ Внимание: При миграции баз данных между серверами с разным часовым поясом значения в полях типа ДатаВремя могут сдвинуться. Всегда проверяйте логику работы с датами после переноса инфраструктуры.

Как влияет високосный год на расчеты?

Функции 1С автоматически учитывают високосные годы. При добавлении одного месяца к дате 31 января система корректно перейдет на 28 (или 29) февраля, не выдавая ошибку.

Часто задаваемые вопросы (FAQ)

Можно ли просто обнулить время математически, вычитая секунды?

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

В чем разница между типом Дата и ДатаВремя в 1С?

В современной платформе 1С:Предприятие 8 существует единый тип Дата, который внутренне хранит и дату, и время. Типа, хранящего только дату без времени, физически не существует. «Дата без времени» — это логическое понятие, означающее дату со временем 00:00:00.

Как отделить дату от времени в СКД (Системе Компоновки Данных)?

В настройках СКД вы можете использовать функцию НачалоПериода с периодичностью «День». Это автоматически сгруппирует данные по дням, отбросив временную составляющую в отчетах. В выражениях ресурсов также доступна функция НАЧАЛОДНЯ.

Почему запрос с НАЧАЛОДНЯ работает медленно?

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