В системе 1С:Предприятие часто возникает необходимость отделить календарную дату от временной метки. Это актуально при формировании отчетов, выводе информации в печатные формы или при записи данных в регистры, где точное время операции не имеет значения.
Разработчики и пользователи сталкиваются с тем, что тип данных ДатаВремя по умолчанию содержит и дату, и время, часто до сотых долей секунды. Игнорирование этой особенности может привести к некорректной фильтрации выборок или визуальному «мусору» в интерфейсе программы.
В данной статье мы рассмотрим несколько проверенных способов решения этой задачи: от использования встроенных функций языка запросов до специфических настроек пользовательского интерфейса.
Проблема типа данных ДатаВремя в платформе 1С
Платформа 1С:Предприятие использует единый тип данных для хранения моментов времени. Объект типа ДатаВремя всегда содержит полную информацию: год, месяц, день, час, минуту и секунду. Даже если пользователь вводит только число, месяц и год, система автоматически дополняет значение нулевым временем (00:00:00).
При выводе таких данных на экран или в отчет часто отображается полная строка, включая нули времени, что выглядит непрофессионально и загромождает интерфейс. Более того, при сравнении двух дат, одна из которых содержит время 14:30, а другая 00:00, прямое сравнение оператором = вернет ложный результат, хотя календарно это один и тот же день.
Понимание внутренней структуры хранения данных критически важно для написания корректного кода. Ошибка в логике обработки времени может привести к тому, что документы «потеряются» в отчетах за текущий день, если они были проведены после полуночи.
⚠️ Внимание: Никогда не пытайтесь обрезать строковое представление даты функциями работы со строками (например, Лев или Сред) до преобразования типа. Это ненадежный метод, который сломается при смене локали или формата даты в настройках пользователя.
Использование встроенной функции НачалоДня()
Самый надежный и рекомендуемый способ получить дату без времени в коде 1С — использование встроенной функции НачалоДня(). Эта функция принимает значение типа ДатаВремя и возвращает новую дату, у которой время принудительно установлено в 00:00:00.
Функция работает как в обычном коде модуля, так и внутри запросов. Она является стандартным инструментом для нормализации временных меток. При использовании в запросе оптимизатор платформы 1С корректно обрабатывает эту функцию, позволяя эффективно использовать индексы по полям даты.
Пример использования в коде модуля выглядит следующим образом:
ТекущаяДата = ТекущаяДата();
ТолькоДата = НачалоДня(ТекущаяДата);
В результате выполнения этого кода переменная ТолькоДата будет содержать значение типа Дата, но с обнуленным временем. Это позволяет безопасно сравнивать даты между собой, игнорируя временную составляющую.
Функция НачалоДня() также полезна для группировки данных в отчетах. Если сгруппировать записи по НачалоДня(ДатаДокумента), вы получите сводку продаж именно по дням, а не по часам проведения.
Преобразование типов и работа с форматной строкой
Иногда требуется не изменить само значение в памяти, а лишь изменить способ его отображения для пользователя. В этом случае преобразование типа данных не требуется, достаточно настроить форматную строку элемента управления или поля вывода.
В конфигураторе или в режиме предприятия можно задать формат отображения поля. Для этого используется специальная строка формата, где указывается шаблон вывода. Использование форматов предпочтительно, когда нужно сохранить исходные данные в базе, но показать их пользователю в упрощенном виде.
Основные коды форматирования для работы с датой:
- 📅 ДЛФ — Длинный формат даты (например, 25 октября 2023 г.)
- 📆 КДФ — Краткий формат даты (например, 25.10.23)
- ⏰ ВФ — Формат времени (используется, если нужно оставить только время)
- 🗓️ ДФ — Пользовательский формат даты через шаблоны (ДД.ММ.ГГГГ)
Чтобы применить формат в коде, используется конструктор Формат(). Он позволяет гибко настраивать вывод, добавляя пояснения или изменяя порядок элементов. Это особенно важно при формировании печатных форм документов, где требования к оформлению могут быть строгими.
СтрокаДляВывода = Формат(ДатаДокумента, "ДФ=ДД.ММ.ГГГГ");
Такой подход гарантирует, что на печати или в отчете будет отображаться только дата, независимо от того, какое время хранится в базе данных. При этом само значение переменной остается неизменным.
Особенности работы с датами в запросах 1С
При написании запросов к базе данных разработчики часто совершают ошибку, пытаясь сравнить поле типа ДатаВремя с датой, введенной пользователем в форму отбора. Если пользователь выбрал «25.10.2023», система может интерпретировать это как «25.10.2023 00:00:00».
Если в базе есть документ, проведенный в 15:30 того же дня, условие ГДЕ Дата = &Период не выполнится, так как 00:00:00 не равно 15:30:00. Для корректной выборки всех документов за указанный день необходимо использовать диапазон дат или функцию усечения времени.
Правильный подход к формированию условия отбора по дате в запросе:
- 🔍 Использовать функцию
НачалоДня()для поля в таблице базы данных. - 📉 Использовать диапазон
Между НачалоДня(&Дата) И КонецДня(&Дата). - ⚙️ Применять параметр запроса, в котором время уже обнулено перед передачей в запрос.
Использование диапазона часто является более производительным решением, чем применение функций к полям таблицы, так как это позволяет механизму 1С эффективнее использовать индексы. Однако для простых выборок функция НачалоДня в условии ГДЕ вполне допустима и читаема.
Почему не стоит хранить дату и время в разных полях?
Некоторые разработчики пытаются создать два отдельных реквизита: «Дата» и «Время». Это нарушает принципы реляционной базы данных 1С, усложняет сортировку и делает невозможным использование стандартных механизмов периодических регистров. Всегда используйте единый тип ДатаВремя.
Таблица сравнения методов обработки даты
Для наглядности приведем сравнение основных подходов к работе с датой без времени. Выбор метода зависит от конкретной задачи: нужно ли изменить данные, как они хранятся, или только как они показываются.
| Метод | Изменяет данные | Где применяется | Производительность |
|---|---|---|---|
НачалоДня() |
Да (создает новое значение) | Код, Запросы | Высокая |
Формат() |
Нет (только вывод) | Отчеты, Печать | Средняя |
| Настройка свойств поля | Нет (визуально) | Формы, Табличные поля | Высокая |
| Преобразование в Строку | Да (смена типа) | Выгрузка в файлы | Низкая |
Как видно из таблицы, для логических операций и фильтрации лучше всего подходит функция НачалоДня(). Она работает непосредственно с типом данных и не требует затрат на преобразование в текст. Визуальные же задачи лучше решать через настройки форматирования.
Частые ошибки и предупреждения при работе со временем
Одной из самых распространенных ошибок является попытка сравнить дату из интерфейса с датой из базы без учета часового пояса или летнего времени, хотя в современной платформе 1С это нивелировано. Более актуальна проблема «границы дней».
Если вы выгружаете данные в сторонние системы (например, в Excel или CRM), убедитесь, что при конвертации типа ДатаВремя в Строка не теряется информация о времени, если она вдруг понадобится позже. Обратное преобразование строки «25.10.2023» в дату снова даст 00:00:00.
⚠️ Внимание: При работе с веб-сервисами и JSON помните, что формат передачи даты может отличаться. Сервер 1С может отправить дату в формате ISO 8601, где время будет присутствовать обязательно. Клиентское приложение должно само решать, как отображать эту дату.
Также стоит учитывать, что функция КонецДня() возвращает время 23:59:59.99, а не 24:00:00. Это важно при построении интервалов. Если вы используете условие Дата < КонецДня(Сегодня), документы, проведенные ровно в 23:59:59.99, могут быть исключены из выборки из-за погрешности округления.
☑️ Проверка корректности даты
FAQ: Вопросы и ответы по датам в 1С
Как получить текущую дату без времени одной строкой кода?
Для этого используйте выражение НачалоДня(ТекущаяДата()). Оно вернет значение типа Дата, соответствующее сегодняшнему дню с временем 00:00:00.
Почему в отчете дата отображается с временем, хотя я выбрал только дату?
Скорее всего, в макете отчета или в свойстве поля табличного документа не задан формат вывода. Проверьте свойство Формат и установите значение ДФ=ДД.ММ.ГГГГ или выберите краткий формат даты.
Можно ли хранить в базе только дату, отключив время?
Нет, в типе данных 1С невозможно физически отключить хранение времени. Тип ДатаВремя всегда содержит полную информацию. Убрать время можно только логически (обнулив его) или визуально (скрыв при отображении).
Как перевести строку "25.10.2023" в тип Дата с нулевым временем?
Используйте функцию Дата() с параметрами или преобразование типа. Пример: Дата(2023, 10, 25) создаст дату с нулевым временем. Если строка приходит извне, используйте ДатаВремя(СтрокаДата), а затем НачалоДня().
Главное правило работы с датами в 1С: всегда явно управляйте временной составляющей. Не полагайтесь на то, что система «сама поймет», что вам нужна только дата. Используйте НачалоДня() для логики и Формат() для отображения.