xsd date and dateTime types restriction

6 марта 2021

Жизненная ситуация

Повидав немало xsd-схем, я обнаружил, что мало кто использует ограничения на типы даты / времени. Бывает все в схеме по максимуму ограничат, даже больше, чем нужно, а дата и время в используется исходном базовом типе.

Проблематика

Какие в такой ситуации я вижу риски при интеграции систем посредством обмена данными через XML-фалйы:

  • Пропуск при валидации по схеме "дефолтного" значения даты

    Дело в том, что в некоторых базах данных в полях с типом даты и даты / времени вместо значения null (пустого значения используется какое-нибудь минимальное значение, типо 1900-01-01.

    Что это значит.

    А то что при передаче данных по xsd-схеме дата, например, является обязательной, а в интегрируемой системе не реализовано ее корректного заполнения, и система заполнит ее "пустым" значением, например, тем же 1900-01-01. Передаст совсем не бизнесовую дату, которая сломает далее по процессу всю логику

  • Использование неправильного значения времени и даже даты из-за часовых поясов

    Мало кто заморачивается указанием часовых поясов в типах даты / времени xml-файлов, а это может привести к ошибкам, даже если при обмене оба сервера находятся в одном часовом поясе. Просто потому что при развертывании сервера забыли указать для него правильный часовой пояс, и он использует время Гринвича.

    А при обмене между разными часовыми поясами, пож-та, не надо думать, что все сервера настроены на московское время всегда

Решение

У этих описанных выше двух рисков есть одно простое покрытие: использование паттерна ограничения значений.

Ниже приведены примеры такого ограничения. Диапазон значения дат можно менять по вкусу, но с учетом "дефолтного" значения даты в используемой интегрируемой системой базе данных

  • Тип времени и даты


    <xsd:simpleType name="typeTimeStamp">
       <xsd:restriction base="xsd:dateTime">
          <xsd:pattern value="2[0-9][0-9][0-9]-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])T[0-2][0-9]:[0-5][0-9]:[0-5][0-9](\+(0[2-9]|1[0-2]):00|Z)"/>
       </xsd:restriction>
    </xsd:simpleType>
    Данный паттерн обязывает для времени либо явно указать часовой пояс, либо передать приведенное к Гринвичу время
  • Тип даты


    <xsd:simpleType name="typeDate">
       <xsd:restriction base="xsd:date">
          <xsd:pattern value="2[0-9][0-9][0-9]-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])"/>
       </xsd:restriction>
    </xsd:simpleType>

Лирика

В примере выше диапазон дат ограничен третьим тысячелетием. Если вы считаете, что ваша схема будет использоваться и в четвертом тысячелетии, то пример выше можно легко поправить с учетом этого :)

Но вообще лучше подстраховаться и значения годов четвертого тысячелетия не обрубать валидацией, да :) чтобы российский, например, госчиновник следующей цивилизации четвертого тысячелетия, откопав такую схему, не рассердился на человека 21-го века и не отправил в прошлое андроида при исполнении показывать кто тут валидный :)