Каждый разработчик 1С рано или поздно сталкивается с тем, что при интерактивном выборе даты в поле ввода или при программном присвоении значения время неожиданно «обнуляется» и принимает вид 00:00:00. При этом отладчик на той же строчке кода может показывать абсолютно корректное системное время. В этой статье мы подробно разберем, почему так происходит, какие скрытые механизмы платформы «1С:Предприятие» за это отвечают, и как решить проблему раз и навсегда несколькими способами.
Прежде чем приступать к исправлению ошибок, проанализируем, как платформа работает с датами. В системе «1С:Предприятие» тип данных Дата всегда содержит в себе две составляющие: календарную дату (год, месяц, день) и время (часы, минуты, секунды). Платформа физически не умеет хранить «чистую» дату без времени или «чистое» время без даты. Если мы записываем в базу только дату, время автоматически устанавливается в начало дня — 00:00:00. Если мы записываем только время, платформа неявно подставляет пустую дату — 01.01.0001.
Следовательно, если у вас пропадает время, проблема кроется исключительно в настройках отображения, ограничениях метаданных или логике работы интерактивного элемента на форме.
Как показывает практика и обсуждение на форуме, это самая частая причина «исчезновения» времени. У элемента управления (Поля ввода) на форме есть свойство Формат (или Формат редактирования). Если там жестко задан шаблон, не предусматривающий вывод времени, платформа будет визуально отсекать его или даже перезаписывать при изменении значения.
Рассмотрим, как настроен локальный формат даты (параметр ДЛФ) и за что отвечают его ключевые значения:
ДЛФ=Д — выводится только дата в числовом формате (например, 04.09.2019). Время при этом игнорируется при отображении.ДЛФ=ДД — длинный формат даты с текстовым названием месяца (например, 4 сентября 2019 г.).ДЛФ=В — выводится только время (например, 16:58:24).ДЛФ=ДВ — выводится и дата, и время (например, 04.09.2019 16:58:24). Это именно то, что нужно в большинстве случаев.ДЛФ=ДДВ — длинный формат даты вместе со временем (например, 4 сентября 2019 г. 16:58:24).Выясним причину проблемы автора темы: у него в свойстве поля ввода был прописан формат, ограничивающий вывод времени, либо форматная строка была составлена с ошибками. Чтобы исправить это, выполните следующие шаги:
ДЛФ=ДВ).Иногда разработчики путают свойства самого элемента формы (Поля ввода) и свойства реквизита, к которому это поле привязано (например, реквизита документа, справочника или самой формы). Если у вас в метаданных для реквизита установлен тип Дата с составом даты «Только дата», то никакие манипуляции с форматом поля ввода не помогут.
Проанализируем эту ситуацию по шагам:
ДатаТП1 = ТекущаяДата() переменная действительно получает полное значение с текущим временем (например, 04.09.2019 16:58:24). Именно это вы и видите в отладчике.04.09.2019 00:00:00. На форме вы снова видите нули.Решение: Найдите исходный реквизит в дереве метаданных конфигурации или в списке реквизитов формы. Перейдите в его свойства, найдите параметр Состав даты и измените его значение на «Дата и время».
Когда пользователь нажимает кнопку выбора (три точки или стрелочку вниз) в поле ввода даты, открывается стандартный календарь. При выборе конкретного дня платформа по умолчанию подставляет время 00:00:00, так как в самом календаре изначально нет ползунков для выбора часов и минут (это справедливо для старых версий платформы и обычных форм).
Если вам требуется, чтобы при выборе даты пользователем автоматически подставлялось текущее время компьютера, необходимо использовать обработчик события ПриИзменении. Разберем правильный пример написания такого кода:
&НаКлиенте
Процедура ДатаТП1ПриИзменении(Элемент)
// Проверим, что дата была выбрана, и она не пустая
Если ЗначениеЗаполнено(Объект.ДатаТП1) Тогда
// Объединяем выбранную пользователем дату и текущее системное время
Объект.ДатаТП1 = НачалоДня(Объект.ДатаТП1) + (ТекущаяДатаСеанса() - НачалоДня(ТекущаяДатаСеанса()));
КонецЕсли;
КонецПроцедуры
В этом примере мы берем начало выбранного пользователем дня (чтобы гарантированно сбросить возможное старое время) и прибавляем к нему разницу между текущим временем сеанса и началом сегодняшнего дня. Таким образом, в реквизит запишется выбранный день с точностью до секунды на текущий момент времени.
В клиент-серверной архитектуре «1С:Предприятия» настоятельно рекомендуется избегать использования функции ТекущаяДата(). Рассмотрим почему:
ТекущаяДата() возвращает время того компьютера, на котором выполняется код. Если код выполняется на сервере, расположенном в Москве, а пользователь работает во Владивостоке, то функция вернет московское время. Это приведет к путанице в документах.ТекущаяДатаСеанса() возвращает время сервера, но автоматически скорректированное под часовой пояс конкретного сеанса пользователя. Это гарантирует, что в документы всегда будет записываться локальное время пользователя, независимо от того, где физически находится сервер базы данных.Если вашим пользователям неудобно вводить дату и время в одном поле (поскольку приходится вручную дописывать цифры времени с клавиатуры), можно прибегнуть к удобному визуальному приему без написания сложного программного кода. Платформа 1С позволяет привязать несколько элементов формы к одному и тому же реквизиту.
Выполним следующие действия по шагам:
Объект.ДатаДокумента).ДЛФ=Д (отображаться будет только дата) и оставьте активной кнопку выбора (чтобы открывался календарь).ДЛФ=В (отображаться будет только время), отключите кнопку выбора, но включите свойство Кнопка регулирования (появятся удобные стрелочки «вверх/вниз» для изменения минут и часов).При такой настройке пользователь сможет быстро и наглядно выбрать дату в первом поле из календаря, а во втором поле стрелочками подправить время. Сама платформа «1С:Предприятие» автоматически объединит эти данные в одном реквизите базы данных без вашего вмешательства.