DateTimeFormatter.ISO_OFFSET_DATE_TIME 未按预期工作
DateTimeFormatter.ISO_OFFSET_DATE_TIME not working as expected
基于此 Java 日期时间 - OffsetDateTime.format() Examples article and this official documentation for DateTimeFormatter 我希望我的 OffsetDateTime 被序列化为 2011-12-03T10:15:30+00:00
其中偏移量自其 UTC 以来为 +00:00
。
我无法设法让 OffsetDateTime 以偏移量呈现,它总是只以 'Z' Zulu 呈现。我做错了什么?
这是 Spring Boot 2.0.0.RELEASE,正如您在屏幕截图中看到的,我在 class 路径上有以下模块并已在 objectMapper 中注册,尽管我认为这不是相对的因为这个问题似乎直接与 DateTimeFormatter 有关,所以我的对象映射器只是使用我提供的格式化程序。
它确实有影响,因为正如您在第二个屏幕截图中看到的那样,当我指定 BASIC_ISO_FORMAT
时它确实会产生不同的结果。
我确实在我的 application.properties 中设置了 属性 设置 spring.jackson.date-format= com.fasterxml.jackson.databind.util.ISO8601DateFormat
但据我了解,这对 OffsetDateTime 没有影响,它只支持以前版本的遗留 Date 对象java。顺便改变一下这个似乎没有像预期的那样影响。
如有任何帮助,我们将不胜感激。
使用 ISO_ZONED_DATE_TIME 格式...
使用 BASIC_ISO_FORMAT... 这确实有影响所以我知道格式化程序正在做一些事情,我只是不清楚为什么 ISO_ZONED_DATE_TIME 没有按预期呈现。
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"
功能,不是错误
DateTimeFormatter. ISO_OFFSET_DATE_TIME
的文档告诉您在使用零偏移量(UTC 本身)时期望 Z
而不是 +00:00
。
那个文件说:
The format consists of:
• The ISO_LOCAL_DATE_TIME
• The offset ID.
针对第二个项目 link,offset ID。该页面显示:
There are three formats:
• Z - for UTC (ISO-8601)
• +hh:mm or -hh:mm - if the seconds are zero (ISO-8601)
• +hh:mm:ss or -hh:mm:ss - if the seconds are non-zero (not ISO-8601)
Z
是 ISO 8601 标准的一部分。任何像样的日期时间库都应该能够解析带有 Z
.
的字符串
如果您坚持使用 +00:00
而不是更常见的 Z
,您将需要指定自定义格式模式,如 Ole linked 中所述V.V.
没有-00:00
offset is -00:00 since its UTC.
您在问题中对 -00:00
的使用不正确。 ISO 8601 标准明确禁止这样的值。 UTC 本身的偏移量是正零,而不是负零:+00:00
.
RFC 3339 自称是 ISO 8601 的“配置文件”。RFC 违反了 ISO 8601,允许使用 -00:00
,并赋予它未知偏移量的含义.一个非常糟糕和不明智的选择,恕我直言,令人困惑且不需要。 ISO 8601 已经说明了一个未知的偏移量:只需完全省略偏移量符号即可。
我建议避免这种负零做法和 RFC 3339。
如您所知,将偏移量零(或 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
.
基于此 Java 日期时间 - OffsetDateTime.format() Examples article and this official documentation for DateTimeFormatter 我希望我的 OffsetDateTime 被序列化为 2011-12-03T10:15:30+00:00
其中偏移量自其 UTC 以来为 +00:00
。
我无法设法让 OffsetDateTime 以偏移量呈现,它总是只以 'Z' Zulu 呈现。我做错了什么?
这是 Spring Boot 2.0.0.RELEASE,正如您在屏幕截图中看到的,我在 class 路径上有以下模块并已在 objectMapper 中注册,尽管我认为这不是相对的因为这个问题似乎直接与 DateTimeFormatter 有关,所以我的对象映射器只是使用我提供的格式化程序。
它确实有影响,因为正如您在第二个屏幕截图中看到的那样,当我指定 BASIC_ISO_FORMAT
时它确实会产生不同的结果。
我确实在我的 application.properties 中设置了 属性 设置 spring.jackson.date-format= com.fasterxml.jackson.databind.util.ISO8601DateFormat
但据我了解,这对 OffsetDateTime 没有影响,它只支持以前版本的遗留 Date 对象java。顺便改变一下这个似乎没有像预期的那样影响。
如有任何帮助,我们将不胜感激。
使用 ISO_ZONED_DATE_TIME 格式...
使用 BASIC_ISO_FORMAT... 这确实有影响所以我知道格式化程序正在做一些事情,我只是不清楚为什么 ISO_ZONED_DATE_TIME 没有按预期呈现。
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"
功能,不是错误
DateTimeFormatter. ISO_OFFSET_DATE_TIME
的文档告诉您在使用零偏移量(UTC 本身)时期望 Z
而不是 +00:00
。
那个文件说:
The format consists of:
• The ISO_LOCAL_DATE_TIME
• The offset ID.
针对第二个项目 link,offset ID。该页面显示:
There are three formats:
• Z - for UTC (ISO-8601)
• +hh:mm or -hh:mm - if the seconds are zero (ISO-8601)
• +hh:mm:ss or -hh:mm:ss - if the seconds are non-zero (not ISO-8601)
Z
是 ISO 8601 标准的一部分。任何像样的日期时间库都应该能够解析带有 Z
.
如果您坚持使用 +00:00
而不是更常见的 Z
,您将需要指定自定义格式模式,如 Ole
没有-00:00
offset is -00:00 since its UTC.
您在问题中对 -00:00
的使用不正确。 ISO 8601 标准明确禁止这样的值。 UTC 本身的偏移量是正零,而不是负零:+00:00
.
RFC 3339 自称是 ISO 8601 的“配置文件”。RFC 违反了 ISO 8601,允许使用 -00:00
,并赋予它未知偏移量的含义.一个非常糟糕和不明智的选择,恕我直言,令人困惑且不需要。 ISO 8601 已经说明了一个未知的偏移量:只需完全省略偏移量符号即可。
我建议避免这种负零做法和 RFC 3339。
如您所知,将偏移量零(或 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
.