首页 > 解决方案 > DateTimeFormatter.ISO_OFFSET_DATE_TIME 未按预期工作

问题描述

基于此 Java 日期时间 - OffsetDateTime.format() 示例文章和此DateTimeFormatter的官方文档,我希望我的 OffsetDateTime 被序列化为2011-12-03T10:15:30+00:00偏移量+00:00自其 UTC 以来的偏移量。

我无法设法让 OffsetDateTime 用偏移量渲染,它总是只用'Z' Zulu 渲染。我究竟做错了什么?

在此处输入图像描述

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

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

我确实spring.jackson.date-format= com.fasterxml.jackson.databind.util.ISO8601DateFormat在我的 application.properties 中设置了这个属性,但据我所知,这对 OffsetDateTime 没有影响,它只支持以前版本的 java 中的旧 Date 对象。顺便说一句,改变这一点似乎没有预期的影响。

任何帮助,将不胜感激。

使用 ISO_ZONED_DATE_TIME 格式... 使用 ISO_ZONED_DATE_TIME 格式

使用 BASIC_ISO_FORMAT... 这确实有影响,所以我知道格式化程序正在做某事,我只是不清楚为什么 ISO_ZONED_DATE_TIME 没有按预期呈现。 使用 BASIC_ISO_FORMAT

 this.objectMapper = objectMapperBuilder.build()      
      .setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE)
      .disable(SerializationFeature.INDENT_OUTPUT)
      .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
      .disable(SerializationFeature.WRITE_DATES_WITH_ZONE_ID);

 SimpleModule simpleModule = new SimpleModule();
 simpleModule.addSerializer(OffsetDateTime.class, new JsonSerializer<OffsetDateTime>() {
        @Override
        public void serialize(OffsetDateTime offsetDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
            String formattedDate = DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(offsetDateTime);
            jsonGenerator.writeString(formattedDate);
        }
    });
this.objectMapper.registerModule(simpleModule);

OffsetDateTime now = OffsetDateTime.now();
TimeZone defaultTimeZone = TimeZone.getDefault();
ZoneId defautlZoneOffset = ZoneOffset.systemDefault();
String serializedOffsetDateTime = this.objectMapper.writeValueAsString(now);
//returns -> "2018-06-27T11:45:56.035Z"

标签: spring-bootdatetime-formatdatetimeoffset

解决方案


功能,而不是错误

的文档告诉您在使用零偏移量(UTC 本身)时DateTimeFormatter. ISO_OFFSET_DATE_TIME期望 aZ而不是 a 。+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 VV 链接的问题中所述

没有这样的事情-00:00

自 UTC 以来,偏移量为 -00:00。

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

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

我建议避免这种负零的做法和 RFC 3339。


推荐阅读