При динамическом создании колонок в табличных частях и табличных полях разработчики часто сталкиваются с ситуацией, когда дата отображается вместе со временем (например, 01.01.2024 0:00:00 вместо желаемого 01.01.2024). Разберем, как устроена работа с датами на платформе 1С, почему популярный подход с преобразованием в строку ошибочен и как правильно настроить программное создание колонки.
Проанализируем внутреннее устройство платформы: в 1С физически не существует отдельного типа «только дата». Любое значение типа Дата всегда содержит и календарную часть, и время в диапазоне от 0001-01-01 00:00:00 до 3999-12-31 23:59:59.
Когда мы указываем квалификатор ЧастиДаты.Дата, платформа не удаляет время из структуры хранения, а принудительно устанавливает временную составляющую в 00:00:00 при интерактивном вводе и валидации, а также определяет поведение элемента управления по умолчанию.
Иногда разработчики пытаются решить задачу простым форматированием значения при записи в строку таблицы:
НовСтрока.ПериодРегистрации = Формат(Док.ПериодРегистрации, "ДФ=dd.MM.yyyy");
Выясним, почему такой подход считается грубой ошибкой и приводит к скрытым багам:
01.12.2023 при сортировке окажется раньше, чем 02.01.2022, что полностью ломает хронологию при клике пользователя по заголовку колонки.НачалоМесяца(), КонецДня(), сложение периодов или разность дат без предварительного ручного парсинга.Посмотрим на классическое решение для табличного поля в обычном приложении. Чтобы колонка имела строгий тип Дата и скрывала время, передадим в конструктор ОписаниеТипов объект КвалификаторыДаты со значением ЧастиДаты.Дата:
Квалификатор = Новый КвалификаторыДаты(ЧастиДаты.Дата);
ТипКолонки = Новый ОписаниеТипов("Дата", , , Квалификатор);
ТабличноеПоле.Колонки.Добавить("ПериодРегистрации", ТипКолонки, "Период регистрации", 10);
Или в компактном виде одной строкой:
ТабличноеПоле.Колонки.Добавить("ПериодРегистрации", Новый ОписаниеТипов("Дата", , , Новый КвалификаторыДаты(ЧастиДаты.Дата)), "Период регистрации", 10);
Если колонка уже создана или типизирована общим типом Дата, правильнее всего изменить представление ячейки через свойство формата, не меняя сам тип хранимых данных:
Колонка = ТабличноеПоле.Колонки.Найти("ПериодРегистрации");
Если Колонка <> Неопределено Тогда
Колонка.Формат = "ДФ=dd.MM.yyyy";
Колонка.ФорматРедактирования = "ДФ=dd.MM.yyyy";
КонецЕсли;
Обратите внимание: свойство ФорматРедактирования необходимо указывать в тех случаях, когда колонка доступна для ручного редактирования пользователем. Без него при входе в режим редактирования ячейки платформа может переключиться на стандартную маску ввода с временем.
Разберем по шагам, как решается аналогичная задача в управляемом интерфейсе, где создание реквизитов и элементов интерфейса разделено на два этапа:
ИзменитьРеквизиты().Посмотрим на пример серверного кода:
&НаСервере
Процедура ДобавитьКолонкуДатыНаСервере()
// Шаг 1. Добавление реквизита в структуру данных формы
МассивРеквизитов = Новый Массив;
Квалификатор = Новый КвалификаторыДаты(ЧастиДаты.Дата);
ТипДатаБезВремени = Новый ОписаниеТипов("Дата", , , Квалификатор);
РеквизитКолонки = Новый РеквизитФормы(
"ПериодРегистрации",
ТипДатаБезВремени,
"ИмяТаблицыФормы",
"Период регистрации"
);
МассивРеквизитов.Добавить(РеквизитКолонки);
ИзменитьРеквизиты(МассивРеквизитов);
// Шаг 2. Создание элемента интерфейса
ТаблицаЭлемент = Элементы.ИмяТаблицыФормы;
НовоеПоле = Элементы.Добавить("ИмяТаблицыФормыПериодРегистрации", Тип("ПолеФормы"), ТаблицаЭлемент);
НовоеПоле.Вид = ВидПоляФормы.ПолеВвода;
НовоеПоле.ПутьКДанным = "ИмяТаблицыФормы.ПериодРегистрации";
НовоеПоле.Формат = "ДФ=dd.MM.yyyy";
НовоеПоле.ФорматРедактирования = "ДФ=dd.MM.yyyy";
КонецПроцедуры
Такой подход обеспечивает сохранение всех преимуществ работы с датами (быстрый поиск, корректная сортировка, использование в математических выражениях) и одновременно гарантирует аккуратный визуальный вывод без лишних нулевых значений времени.