Как правильно настроить формат даты и времени в XML, разобраться с дробными секундами и выгрузить часовой пояс из 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При интеграции 1С:Предприятия с внешними информационными системами (веб-сервисами, государственными порталами, базами данных SQL) разработчики часто сталкиваются с жесткими требованиями к форматам обмена. Одним из наиболее коварных объектов обмена является дата и время. В XML-документах стандарт представления даты-времени регулируется спецификацией W3C XML Schema (тип dateTime). Строка вида 2018-07-09T16:33:04.6396109+03:00 нередко вызывает вопросы у начинающих разработчиков.

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

Разбираемся с дробными секундами (Fractional Seconds)

Рассмотрим детально структуру полной даты в формате XML:

2018-07-09T16:33:04.6396109+03:00

Часть строки после времени секунд перед знаком часового пояса (в нашем примере это .6396109) представляет собой дробную часть секунды (fractional seconds). Давайте разберем, откуда берется именно такое количество символов и зачем это нужно:

  1. Точность до «тиков» (Ticks): В экосистеме Microsoft (.NET Framework, IIS, MS SQL Server) время может измеряться в тактах или «тиках». Один тик равен 100 наносекундам. В одной секунде содержится ровно 10 000 000 тиков. Именно поэтому современные сериализаторы данных часто выводят дробную секунду с точностью до 7 знаков после запятой.
  2. Спецификация XML Schema (W3C): Согласно международному стандарту, количество десятичных знаков в дробной части секунд не ограничено. Это означает, что принимающая сторона (парсер XML) обязана корректно распознавать и обрабатывать даты как вообще без дробной части (16:33:04), так и с любым количеством знаков (например, 16:33:04.63 или 16:33:04.123456789).
  3. Ограничения СУБД: При записи XML-данных в базу данных точность может усекаться. Например, устаревший тип данных datetime в MS SQL Server поддерживает точность лишь до 1/300 секунды (около 3.33 миллисекунды). Из-за этого при записи числа округляются до тысячных долей. Более современный тип datetime2 полноценно поддерживает точность до 7 знаков (100 нс), что идеально соответствует нашему примеру.

Если ваша внешняя система не требует микросекундной точности для сортировки транзакций внутри одной секунды, эти цифры можно безболезненно занулять (например, приводить к виду .0000000) или отбрасывать дробную часть целиком.

Таймзоны в формате XML: рассеиваем популярные заблуждения

Часто возникает путаница: как соотносится указанный в XML часовой пояс с реальным локальным временем? Давайте проанализируем пример:

2018-07-09T16:33:04+03:00

Правило стандарта W3C гласит: время, указанное до знака плюс/минус, является местным временем для того часового пояса, который указан после этого знака.

Особенности работы платформы 1С:Предприятие с XML-датами

Платформа 1С имеет свою специфику при импорте и экспорте значений типа Дата через XML. Выясним эти особенности подробнее.

При чтении XML (Импорт в 1С):
Когда встроенные механизмы 1С (например, XMLЗначение или парсер XDTO) считывают строку даты с указанным часовым поясом, платформа автоматически преобразует ее к часовому поясу текущего сеанса 1С (функция ЧасовойПоясСеанса()).

Представим ситуацию: в XML-файле пришло значение 2017-10-31T12:24:35+00:00 (время по Гринвичу). Если ваш сеанс 1С запущен в Москве (UTC+3), то при чтении функция 1С вернет дату 31.10.2017 15:24:35. Платформа самостоятельно прибавила 3 часа, чтобы локальный пользователь увидел корректное время на своем экране. Это очень удобно и предотвращает ошибки временных сдвигов.

При записи XML (Экспорт из 1С):
Тип Дата в системе 1С:Предприятие является простым типом. Физически в базе данных он хранит только дату и время (год, месяц, день, час, минута, секунда), но не содержит информации о часовом поясе. По этой причине стандартный СериализаторXDTO или базовая функция XMLСтрока() выгружают дату «как есть», без указания смещения часового пояса (например, просто 2018-07-09T16:33:04).

Практические методы выгрузки даты с часовым поясом из 1С

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

Способ 1. Приведение к стандарту UTC (Рекомендуемый подход)

В современной веб-разработке стандартом де-факто считается передача времени в универсальном формате UTC с суффиксом Z на конце. Это исключает любые разночтения. Перед выгрузкой мы переводим нашу локальную дату в универсальное время и вручную добавляем символ часового пояса.

Рассмотрим пример кода:


// Предположим, у нас есть локальная дата документа
ЛокальнаяДата = Объект.Дата; // Например, 09.07.2018 16:33:04

// Переводим локальное время сеанса в универсальное UTC
УниверсальнаяДата = УниверсальноеВремя(ЛокальнаяДата);

// Сериализуем в стандартную строку XML и добавляем маркер UTC
СтрокаXML = XMLСтрока(УниверсальнаяДата) + "Z";
// Результат: "2018-07-09T13:33:04Z"

Способ 2. Программное вычисление и добавление смещения таймзоны

Если принимающая сторона требует передавать именно локальное время со смещением (например, +03:00), нам придется вычислить разницу часовых поясов сеанса вручную, так как встроенный метод Формат() в 1С не поддерживает маску вывода смещения таймзоны (символы zzz).

Давайте разберем по шагам, как написать универсальную функцию для формирования такой строки:


Функция ПолучитьДатуВФорматеXMLСЧасовымПоясом(Знач ИсходнаяДата) Экспорт
    
    // Получаем текущее локальное и универсальное время для расчета смещения
    ТекущееВремяСеанса = ТекущаяДатаСеанса();
    ТекущееВремяUTC    = УниверсальноеВремя(ТекущееВремяСеанса);
    
    // Вычисляем разницу часовых поясов в секундах
    РазницаСекунд = ТекущееВремяСеанса - ТекущееВремяUTC;
    СмещениеЧасов = Цел(РазницаСекунд / 3600);
    СмещениеМинут = Цел((РазницаСекунд % 3600) / 60);
    
    // Формируем строковое представление смещения часового пояса
    ЗнакСмещения = ?(РазницаСекунд >= 0, "+", "-");
    СтрокаСмещения = ЗнакСмещения 
                     + Формат(Абс(СмещениеЧасов), "ЧЦ=2; ЧДЦ=0; ЧГ=0") 
                     + ":" 
                     + Формат(Абс(СмещениеМинут), "ЧЦ=2; ЧДЦ=0; ЧГ=0");
    
    // Собираем итоговую XML-строку без миллисекунд
    СтрокаДаты = Формат(ИсходнаяДата, "ДФ=yyyy-MM-ddTHH:mm:ss");
    
    Возврат СтрокаДаты + СтрокаСмещения;
КонецФункции

Данный метод вернет строку в точном соответствии со спецификацией W3C, например: 2018-07-09T16:33:04+03:00. Это решение является полностью автономным и не зависит от сторонних библиотек.

Способ 3. Кастомизация типов в пакетах XDTO

Если выгрузка XML-документа происходит с использованием фабрики XDTO и валидацией по схеме (XSD), то попытка записать сформированную вручную строку в свойство с типом dateTime вызовет ошибку несоответствия типов платформы 1С.

Чтобы обойти это ограничение, проанализируем следующий прием:

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

← На главную