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

Частая задача при формировании отчетов или отборов — необходимость игнорировать время, оставив только календарный день. Например, при группировке продаж по дням или при поиске документов, созданных в конкретную дату, независимо от часа и минуты. Существует несколько подходов к решению этой проблемы, и выбор конкретного метода зависит от контекста: пишете ли вы код на встроенном языке или формируете запрос к базе данных.

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

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

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

Когда вы создаете дату вручную, например, Новая Дата(2023, 10, 25), система автоматически подставляет нулевое время (00:00:00). Однако, если дата получена из поля документа или регистра, она с высокой вероятностью будет содержать ненулевое время, соответствующее моменту проведения или создания объекта. Именно эта «хвостовая» часть часто мешает корректным сравнениям.

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

💡

Помните, что в 1С минимальная granularity (точность) даты — одна секунда. Миллисекунды при стандартной работе обычно отсекаются или округляются, но секунды играют критическую роль при точных сравнениях.

Использование функции НачалоДня в запросах

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

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

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

ВЫБРАТЬ

Продажи.Ссылка,

Продажи.Дата,

НАЧАЛОДНЯ(Продажи.Дата) КАК ДатаБезВремени

ИЗ

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

ГДЕ

НАЧАЛОДНЯ(Продажи.Дата) = &НужнаяДата

Такой подход гарантирует, что все документы, созданные с 00:00:01 до 23:59:59 указанного дня, будут корректно обработаны. Функция НачалоДня является детерминированной и оптимизируется движком запросов, что делает её предпочтительным выбором в 90% случаев.

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

Обрезка времени через форматирование строки

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

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

В языке запросов 1С также доступна функция ФОРМАТ(), которая позволяет гибко управлять отображением. Вы можете задать шаблон, в котором будут присутствовать только день, месяц и год. Это особенно полезно при выгрузке данных в CSV или XML файлы, где формат даты строго регламентирован.

  • 📅 Функция Формат(Дата, "ДФ=dd.MM.yyyy") вернет строку вида «25.10.2023».
  • ⏱ Использование Строка(Дата) без параметров вернет полную дату с временем, что часто избыточно.
  • 🔄 Обратное преобразование строки в дату выполняется функцией Дата(), но требует строгого соответствия формата.

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

Почему не стоит хранить дату как строку?

Хранение даты в строковом поле лишает вас возможности использовать встроенные функции работы с периодами, такие как ДобавлениеМесяца или РазностьДат. Кроме того, сортировка строк «01.02.2023» и «10.01.2023» будет происходить лексикографически, а не хронологически, что приведет к хаосу в отчетах.

Манипуляции со временем в коде на встроенном языке

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

Один из распространенных, но не самых эффективных методов — использование функции СтрЗаменить() над строковым представлением даты с последующим преобразованием обратно. Этот подход считается «грязным», так как зависит от региональных настроек компьютера пользователя. Если у пользователя формат даты «день/месяц/год», а код рассчитан на «год-месяц-день», произойдет ошибка.

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

ИсходнаяДата = ТекущаяДата();

НоваяДата = Дата(Год(ИсходнаяДата), Месяц(ИсходнаяДата), День(ИсходнаяДата));

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

💡

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

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

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

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

Метод Где выполняется Скорость Надежность
НАЧАЛОДНЯ() в запросе Сервер БД (SQL) Высокая Максимальная
Конструктор Дата(Год, Месяц, День) Сервер 1С / Клиент Средняя Высокая
СтрЗаменить() + Дата() Сервер 1С / Клиент Низкая Низкая (зависит от локали)
Форматирование в строку Клиент / Печатная форма Средняя Высокая (для отображения)

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

Особенно это важно в файловых вариантах баз данных, где ресурсы ограничены. Даже в клиент-серверном варианте (PostgreSQL, MS SQL) лишний прогон данных через сервер приложений 1С снижает общую пропускную способность системы. Всегда стремитесь фильтровать и преобразовывать данные как можно «ниже» к уровню хранения.

☑️ Оптимизация работы с датами

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

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

Несмотря на кажущуюся простоту, работа с датами в 1С полна подводных камней. Одна из самых частых ошибок — попытка сравнить дату с временем и дату без времени оператором «Равно». Как упоминалось ранее, 25.10.2023 10:00 не равно 25.10.2023 00:00, хотя для пользователя это один и тот же день.

Другая распространенная проблема возникает при использовании интервалов. Разработчики часто пишут условия вида Дата >= НачалоПериода И Дата <= КонецПериода. Если КонецПериода установлен на начало следующего дня (00:00:00), то документы, созданные в последнюю секунду предыдущего дня, могут не попасть в выборку. Правильнее использовать Дата < КонецСледующегоДня.

⚠️ Внимание: При работе с часовыми поясами в распределенных информационных базах (РИБ) время может смещаться. Функция НАЧАЛОДНЯ() работает с локальным временем сервера, что может привести к рассинхронизации данных между узлами, если они находятся в разных часовых поясах.

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

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

Проблема високосных лет и переходов на летнее время

Хотя функция НачалоДня() корректно обрабатывает високосные годы, при ручном вычитании секунд (например, Дата - Время(Час, Минута, Секунда)) можно столкнуться с ошибками на границах перехода на летнее/зимнее время в регионах, где это актуально. Всегда используйте встроенные функции платформы.

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

Как убрать время из даты в консоли запросов?

В консоли запросов используйте функцию НАЧАЛОДНЯ(ВашаДата) в списке полей или в условиях отбора. Это стандартная функция языка запросов 1С, которая работает во всех конфигурациях.

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

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

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

Иногда обновления платформы 1С затрагивают драйверы СУБД или механизмы сериализации данных. Если вы заметили странности, проверьте релиз-ноты версии платформы. В редких случаях может потребоваться пересборка регистров или обновление конфигурации базы данных.

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

Оберните обе сравниваемые даты в функцию НАЧАЛОДНЯ(). Запрос будет выглядеть так: ГДЕ НАЧАЛОДНЯ(Дата1) = НАЧАЛОДНЯ(Дата2). Это гарантирует корректное сравнение только календарных дней.

Влияет ли удаление времени на индексацию запроса?

Применение функции к полю в условии ГДЕ (например, ГДЕ НАЧАЛОДНЯ(Дата) = ...) может препятствовать использованию индекса по этому полю в некоторых СУБД. Для максимальной скорости лучше формировать диапазон: ГДЕ Дата >= &НачалоДня И Дата < &НачалоСледующегоДня.