DateTimeFormatter.ISO_OFFSET_DATE_TIME无法按预期工作

时间:2018-06-27 13:31:29

标签: spring-boot datetime-format datetimeoffset

基于此Java日期时间-OffsetDateTime.format() Examples文章和DateTimeFormatter的官方文档,我希望将OffsetDateTime序列化为2011-12-03T10:15:30+00:00,其中offset为offset {{1} },因为它是UTC。

我无法使OffsetDateTime具有偏移量进行渲染,它始终仅以'Z'Zulu进行渲染。我在做什么错了?

enter image description here

这是Spring Boot 2.0.0.RELEASE,正如您在屏幕快照中所看到的,我在类路径上具有以下模块并向objectMapper注册,尽管我认为这不是相对的,因为这个问题似乎是直接使用DateTimeFormatter,我的对象映射器只是使用我提供的格式化程序。

它确实有影响,因为正如您在第二个屏幕截图中看到的那样,当我指定+00:00时,它的确产生了不同的结果。

我在我的application.properties中确实设置了此属性BASIC_ISO_FORMAT,但是据我所知,这对OffsetDateTime没有影响,它仅支持Java早期版本中的旧Date对象。顺便更改此似乎没有预期的影响。

任何帮助将不胜感激。

使用ISO_ZONED_DATE_TIME格式... Using ISO_ZONED_DATE_TIME format

使用BASIC_ISO_FORMAT ...确实会产生影响,所以我知道格式化程序正在执行某些操作,但我不清楚为什么ISO_ZONED_DATE_TIME未按预期呈现。 Using BASIC_ISO_FORMAT

spring.jackson.date-format= com.fasterxml.jackson.databind.util.ISO8601DateFormat

2 个答案:

答案 0 :(得分:3)

功能,不是错误

DateTimeFormatter. ISO_OFFSET_DATE_TIME的文档告诉您在使用零偏移量(UTC本身)时期望使用Z而不是+00:00

那个医生说:

  

格式包括:

     

•ISO_LOCAL_DATE_TIME

     

•偏移量ID。

跟随第二项offset ID的链接。该页面上显示:

  

共有三种格式:

     

•Z-适用于UTC(ISO-8601)

     

•+ hh:mm或-hh:mm-如果秒为零(ISO-8601)

     

•+ hh:mm:ss或-hh:mm:ss-如果秒数不为零(不是ISO-8601)

ZISO 8601标准的一部分。任何体面的日期时间库都应该能够使用Z解析字符串。

如果您坚持使用+00:00而不是更常见的Z,则需要指定由Ole V.V链接的the Question中讨论的自定义格式设置模式。

没有-00:00

之类的东西
  

自UTC以来的偏移量是-00:00。

您在问题中使用-00:00是不正确的。 ISO 8601标准明确禁止使用该值。 UTC本身的偏移量为正零,而不是负零:+00:00

RFC 3339宣称自己是ISO 8601的“配置文件”。RFC违反了ISO 8601,允许使用-00:00,并为其指定了未知偏移量的含义。恕我直言,这是一个非常贫穷和不明智的选择,令人困惑和不必要。 ISO 8601已经解决了未知的偏移:只需完全省略偏移符号即可。

我建议同时避免使用负零和RFC3339。

答案 1 :(得分:2)

您知道,将偏移量零(或Zulu)格式化为Z应该可以。这是您使用的标准格式ISO 8601的一部分。但是,如果没有,则为:

    static DateTimeFormatter formatter
            = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssxxx");

    @Override
    public void serialize(OffsetDateTime offsetDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        String formattedDate = formatter.format(offsetDateTime);
        jsonGenerator.writeString(formattedDate);
    }

这将对OffsetDateTime进行序列化,例如2011-12-03T10:14:30+00:00(在标准中也允许)。格式模式字符串中的小写字母x用于格式化偏移量,而对于零偏移量不求助于Z

以上是格式化程序的简短直接声明。由于我希望尽可能地依赖更高级别的标准元素,因此我考虑使用更长的变体:

    static DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
            .appendPattern("xxx")
            .toFormatter();

这将重用标准库中的ISO_LOCAL_DATE_TIME。如果您的时间没有几分之一秒,那么输出将是相同的。如果已包含,则将在后一种情况下将其包括在序列化中,就像使用ISO_OFFSET_DATE_TIME,例如2011-12-03T10:14:30.1234+00:00一样。

极限: Wikipedia article: ISO 8601