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

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

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

Функция НачалоДня как основной инструмент

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

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

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

ТекущаяДатаВремя = ТекущаяДата();

ДатаБезВремени = НачалоДня(ТекущаяДатаВремя);

💡

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

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

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

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

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

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

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

ВЫБРАТЬ

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

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

ИЗ

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

ГДЕ

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

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

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

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

Метод фильтрации Производительность Читаемость кода Рекомендация
Функция НАЧАЛОДНЯ в запросе Средняя Высокая Универсальный вариант
Диапазон (Между ... И ...) Высокая Средняя Для больших выборок
Сравнение с параметром Высокая Высокая Предпочтительный способ
💡

Использование диапазона дат (от начала дня до начала следующего) часто производительнее применения функции к полю в условии WHERE.

Преобразование строки в дату без времени

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

Если строка содержит только дату в формате ДД.ММ.ГГГГ, функция СтрДата автоматически установит время в 00:00:00. Однако, если строка содержит время, а вам нужно его отбросить, потребуется комбинация функций. Сначала выполняется преобразование в дату, а затем применяется НачалоДня для очистки временной метки.

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

  • 📅 Используйте СтрДата() для строк вида "31.12.2023" — время будет нулевым.
  • ⏰ Для строк с временем "31.12.2023 15:30" применяйте НачалоДня(СтрДата(...)).
  • 🛡️ Всегда оборачивайте преобразование в блок обработки исключений.

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

Нюансы региональных настроек

Функции преобразования строк зависят от региональных настроек пользователя. Если формат даты отличается (например, ММ/ДД/ГГГГ), функция может вернуть неверный результат или ошибку. Рекомендуется явно указывать формат или использовать универсальные разделители.

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

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

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

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

⚠️ Внимание: При сравнении дат не используйте оператор «больше или равно» без учета времени, если не очистили время заранее. Запись, созданная в 10:00, будет больше даты начала дня 00:00, что может нарушить логику выборки.

В запросах часто возникает необходимость проверить, попадает ли дата в интервал. Здесь важно понимать, включаются ли границы интервала. Если вы используете конструкцию МЕЖДУ, обе границы включаются в выборку. Поэтому верхняя граница должна быть либо концом дня (23:59:59), либо, что правильнее, началом следующего дня с условием «меньше».

Вывод даты в печатные формы и интерфейсы

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

Для настройки формата в СКД (Система Компоновки Данных) используется поле «Формат». Указание строки формата ДФ='dd.MM.yyyy' скроет время из вывода. Однако для логики программы это не имеет значения — внутри значение по-прежнему содержит время. Такой подход удобен для отчетов, но не подходит для алгоритмических сравнений.

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

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

Если вы разрабатываете внешнюю обработку или отчет, который выгружает данные в Excel, убедитесь, что тип данных передается корректно. Иногда при экспорте дата превращается в строку, и при обратном чтении возникают проблемы. Явное приведение типов перед выгрузкой помогает избежать рассинхронизации данных между 1С и внешними системами.

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

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

Еще одна распространенная проблема возникает при работе с интерфейсом OData или REST. При передаче даты в JSON она часто кодируется в формате ISO 8601 с указанием времени и часового пояса. При приеме таких данных на стороне 1С необходимо корректно распарсить строку и привести её к локальному времени, после чего обнулить время, если бизнес-логика того требует.

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

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

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

💡

Никогда не храните календарные даты в строковых полях — это лишает систему возможности эффективной индексации и корректной сортировки.

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

Используйте конструкцию НачалоДня(ТекущаяДата()). Это вернет дату на сегодняшний день с временем 00:00:00. Это самый быстрый и безопасный способ.

Почему сравнение дат возвращает Ложь, хотя даты одинаковые?

Скорее всего, у одной из дат время не равно 00:00:00. Например, одна дата 10.01.2026 00:00:00, а другая 10.01.2026 12:30:00. Для 1С это разные моменты времени. Примените НачалоДня() к обеим датам перед сравнением.

Можно ли хранить дату без времени в регистре сведений?

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

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

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

Влияет ли часовой пояс на функцию НачалоДня?

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