xsd:dateTime到Java OffsetDateTime

时间:2016-03-02 18:02:16

标签: xml datetime xsd jaxb java-8

为了使用JAXB正确处理xs:dateTime,我必须从String - > java.time.OffsetDateTime编写自己的转换器。

正如XML Schema Definition中所提到的,dateTime的灵感来自ISO 8601.我使用OffsetDateTime.parse(s, DateTimeFormatter.ISO_OFFSET_DATE_TIME)来解析xs:dateTime,这适用于例如{8}。

"2007-12-03T10:15:30+01:00" //or
"2007-12-03T10:15:30Z"

可悲的是,在xs:dateTime偏移部分is declared optional中,所以解析有效的

"2016-03-02T17:09:55"

抛出DateTimeParseException

OffsetDateTime是否有DateTimeFormatter,它还处理未分区的xs:dateTime(可能带有默认时区)?

3 个答案:

答案 0 :(得分:5)

我认为没有内置版本,但您可以在DateTimeFormatterBuilder课程的帮助下自行制作。

您可以指定用方括号括起来的可选偏移量,即[XXXXX](以匹配"+HH:MM:ss"),然后,您可以提供默认偏移量(parseDefaulting)不在场。如果要默认为UTC,可以设置0以指定无偏移量;如果要默认使用VM的当前偏移量,可以使用OffsetDateTime.now().getLong(ChronoField.OFFSET_SECONDS)

public static void main(String[] args) {
    String[] dates = {
        "2007-12-03T10:15:30+01:00",
        "2007-12-03T10:15:30Z",
        "2016-03-02T17:09:55",
        "2016-03-02T17:09:55Z"
    };
    DateTimeFormatter formatter =
        new DateTimeFormatterBuilder().appendPattern("yyyy-MM-dd'T'HH:mm:ss[XXXXX]")
                                      .parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
                                      // or OffsetDateTime.now().getLong(ChronoField.OFFSET_SECONDS)
                                      .toFormatter();
    for (String date : dates) {
        System.out.println(OffsetDateTime.parse(date, formatter));
    }
}

答案 1 :(得分:1)

只是为了显示我当前的解决方案,它将未分区的格式解析为当前解析日期时间中的系统默认偏移量。

public static OffsetDateTime parseDateTime(String s) {
    if (s == null) {
        return null;
    }
    try {
        return OffsetDateTime.parse(s, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
    } catch (DateTimeParseException e) {
        try { // try to handle zoneless xml dateTime
            LocalDateTime localDateTime = LocalDateTime.parse(s, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
            ZoneOffset offset = ZoneId.systemDefault().getRules().getOffset(localDateTime);
            return OffsetDateTime.of(localDateTime.toLocalDate(), localDateTime.toLocalTime(), offset);
        } catch (Exception fallbackTryException) {
            throw e;
        }
    }
}

答案 2 :(得分:0)

jTextTime库可以解决此问题。这是Maven Central提供的最小的非dep库。它处理缺少时区偏移的情况。

该库包含预构建XmlAdapters,因此您可以使用下面的示例对您的类进行注释:

public class Customer {

    @XmlElement
    @XmlJavaTypeAdapter(OffsetDateTimeXmlAdapter.class)
    @XmlSchemaType(name="dateTime")
    public OffsetDateTime getLastOrderTime() {
        ....
    }

    @XmlElement
    @XmlJavaTypeAdapter(OffsetDateXmlAdapter.class)
    @XmlSchemaType(name="date")
    public OffsetDateTime getDateOfBirth() {   // returns a date-only value
        ....
    }
}

或者,您可以在包级别进行注释,这样就不必为每个类和每个属性都进行注释。

如果您对缺少时区偏移量的情况下库的默认处理不满意,则可以customize

全部披露:我是jTextTime的作者。