При интеграции систем 1С со сторонними веб-сервисами и базами данных разработчики регулярно сталкиваются с необходимостью передачи даты и времени. Стандартом обмена в XML-документах для этого служит формат dateTime (определенный консорциумом W3C). Попытки сформировать эту строку вручную с помощью встроенной функции Формат() часто приводят к неявным ошибкам валидации XDTO, таким как "Несоответствие типов XDTO: Значение не соответствует простому типу".
В этой статье мы подробно разберем, почему возникают такие ошибки, как устроена работа с типами даты/времени в платформе 1С, и рассмотрим правильные механизмы заполнения свойств XDTO для бесперебойного обмена данными.
Рассмотрим классический пример, с которого часто начинают разработчики. Допустим, у нас есть свойство XDTO-пакета с именем EstimatedDeliveryDate, имеющее тип dateTime (пространство имен http://www.w3.org/2001/XMLSchema). По спецификации XML Schema данный тип должен иметь вид ГГГГ-ММ-ДДTЧЧ:ММ:СС (например, 2018-09-19T16:25:04), где латинская буква T выступает обязательным разделителем между датой и временем.
Попытка установить значение свойства через ручное форматирование выглядит так:
// Попытка ручного форматирования строки с разделителем 'T'
ХДТОХедер.EstimatedDeliveryDate = Формат(Объект.ДатаПриходаУхода, "ДФ='гггг-ММ-ддТЧЧ:мм:сс'");
Этот код приводит к падению платформы с ошибкой:
"Ошибка проверки данных XDTO: Значение: '2018-09-19Т16:25:04' не соответствует простому типу".
Почему так происходит? Дело в том, что фабрика XDTO в 1С осуществляет строгую валидацию типов. Если в схеме XSD (или пакете XDTO) свойство описано типом dateTime, то платформа ожидает, что в качестве значения ей передадут нативный объект 1С с типом Дата, а не текстовую строку Строка. При попытке записать туда строку (пусть даже идеально похожую на XML-дату) фабрика XDTO отвергает ее, так как тип значения (Строка) не соответствует ожидаемому типу метаданных (Дата/dateTime).
Если же мы уберем разделитель T и запишем дату в более простом строковом формате, платформа все равно вернет ошибку несовместимости типов, либо (в редких случаях нестрогой проверки) запишет пустую дату 0001-01-01 или дату без учета времени.
---
Самый простой, лаконичный и архитектурно правильный способ — это передача стандартного объекта 1С Дата напрямую в свойство XDTO-объекта. Платформа 1С «под капотом» сама знает правила сериализации своих типов данных в XML-форматы. Она автоматически переведет дату в нужный текстовый вид и самостоятельно подставит букву T в качестве разделителя при генерации XML-пакета.
Давайте посмотрим на пример правильного заполнения свойства:
// Прямая передача нативного типа Дата в объект XDTO
ХДТОХедер.EstimatedDeliveryDate = Объект.ДатаПриходаУхода;
В этом случае при выгрузке XML платформа сама сформирует валидную строку:
<EstimatedDeliveryDate>2018-09-19T16:25:04</EstimatedDeliveryDate>
Никаких ошибок валидации не возникнет, так как фабрика XDTO успешно сопоставит тип данных 1С Дата с типом схемы dateTime.
---
Если вам по какой-то причине необходимо получить именно строковое представление даты по стандарту XML (например, при ручном формировании текста XML-запроса через ЗаписьXML без использования структуры XDTO), воспользуйтесь встроенной функцией 1С XMLСтрока().
Разберем пример ее использования:
// Преобразование даты в формат XML-строки
СтроковоеПредставлениеДаты = XMLСтрока(Объект.ДатаПриходаУхода);
// На выходе получим строку вида: "2018-09-19T16:25:04"
Обратите внимание: если вы присвоите результат работы функции XMLСтрока() свойству XDTO, имеющему строгий тип dateTime, вы можете вновь столкнуться с ошибкой валидации на некоторых конфигурациях и релизах платформы, так как функция возвращает тип Строка. Используйте XMLСтрока() только для полей, которые в схеме XDTO объявлены как текстовые (string), либо при прямой записи в XML-документ.
---
Многие современные API (особенно зарубежные веб-сервисы) требуют передачи времени строго с указанием часового пояса в формате ISO 8601 (например, 2018-11-28T14:00:07+03:00 или 2018-11-28T11:00:07Z для UTC).
Здесь кроется важная архитектурная особенность 1С: встроенный тип данных Дата в 1С не хранит информацию о часовом поясе.
Если вы передадите объект Дата напрямую в XDTO-свойство типа dateTime, то в итоговом XML часовой пояс указан не будет. Это может привести к тому, что принимающая сторона неверно интерпретирует ваше локальное время.
Рассмотрим, как решить эту проблему в зависимости от структуры вашей XDTO-схемы:
Если схема веб-сервиса позволяет передавать дату как строку, мы можем вручную сформировать дату со смещением, используя функцию XMLСтрока() и конкатенацию:
// Формируем дату со смещением московского часового пояса (+03:00)
ХДТОХедер.EstimatedDeliveryDate = XMLСтрока(ТекущаяДата()) + "+03:00";
// Результат в XML: 2018-11-28T14:00:07+03:00
Если схема требует строго dateTime, попытка дописать строку со смещением (+03:00) напрямую вызовет ошибку валидации фабрики. В этом случае лучшей практикой является приведение времени к универсальному координированному времени (UTC) перед отправкой:
// Переводим местное время сеанса в UTC (Гринвич)
ДатаВФорматеUTC = УниверсальноеВремя(Объект.ДатаПриходаУхода);
// Передаем дату в XDTO
ХДТОХедер.EstimatedDeliveryDate = ДатаВФорматеUTC;
Хотя в итоговом XML не будет символа Z на конце, большинство принимающих систем по умолчанию трактуют полученную дату без указания смещения как UTC (или это регламентируется правилами интеграции сторонних систем).
---
Спецификация W3C для типа dateTime поддерживает дробную часть секунды (миллисекунды, например, 2018-09-19T16:25:04.123). Стандартный тип Дата в 1С имеет точность только до одной секунды.
Если внешняя система присылает вам данные с миллисекундами, при чтении XML через фабрику XDTO платформа 1С автоматически отбросит дробную часть секунд и запишет в базу стандартную дату.
Если же внешнее API строго требует передачи миллисекунд от вас, вам придется переопределить это поле в схеме XDTO как string и формировать его вручную программным путем.
---
Для минимизации ошибок при работе с датами рекомендуем придерживаться следующих правил:
Дата. Не пытайтесь форматировать их через функцию Формат().dateTime (если важны и дата, и время), date (если нужно передать только день без времени) или time (только время). Платформа 1С автоматически отсечет лишние компоненты при выгрузке типов date и time.УниверсальноеВремя() перед ее записью в объект XDTO.Применяя эти подходы, вы обеспечите быструю и корректную сериализацию данных, избавив себя от рутины ручного парсинга строк и снизив вероятность появления ошибок интеграции до нуля.