这两个值实际上代表2017-01-01T01:01:01.000000001Z
同2017-01-01T01:01:01.000000001Z[UTC]
一个瞬间,所以它们是等价的,可以毫无问题地使用(至少应该没有问题,因为它们代表同一个瞬间)。
唯一的细节是,由于某种原因,JacksonZoneId
在反序列化时将值设置为“UTC”,在这种情况下这是多余的(Z
已经告诉偏移量是“UTC”)。但它不应该影响日期值本身。
摆脱这[UTC]
部分的一个非常简单的方法是将这个对象转换为OffsetDateTime
(因此它保持Z
偏移并且不使用[UTC]
区域)然后再返回到ZonedDateTime
:
ZonedDateTime z = // object with 2017-01-01T01:01:01.000000001Z[UTC] value
z = z.toOffsetDateTime().toZonedDateTime();
System.out.println(z); // 2017-01-01T01:01:01.000000001Z
之后,z
变量的值将是2017-01-01T01:01:01.000000001Z
(没有[UTC]
部分)。
但当然这并不理想,因为您必须在所有日期手动执行此操作。更好的方法是编写一个自定义反序列化器(通过扩展),当它是UTCcom.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer
时不设置时区:
public class CustomZonedDateTimeDeserializer extends InstantDeserializer<ZonedDateTime> {
public CustomZonedDateTimeDeserializer() {
// most parameters are the same used by InstantDeserializer
super(ZonedDateTime.class,
DateTimeFormatter.ISO_ZONED_DATE_TIME,
ZonedDateTime::from,
// when zone id is "UTC", use the ZoneOffset.UTC constant instead of the zoneId object
a -> ZonedDateTime.ofInstant(Instant.ofEpochMilli(a.value), a.zoneId.getId().equals("UTC") ? ZoneOffset.UTC : a.zoneId),
// when zone id is "UTC", use the ZoneOffset.UTC constant instead of the zoneId object
a -> ZonedDateTime.ofInstant(Instant.ofEpochSecond(a.integer, a.fraction), a.zoneId.getId().equals("UTC") ? ZoneOffset.UTC : a.zoneId),
// the same is equals to InstantDeserializer
ZonedDateTime::withZoneSameInstant, false);
}
}
然后你必须注册这个反序列化器。如果您使用ObjectMapper
,则需要将其添加到JavaTimeModule
:
ObjectMapper objectMapper = new ObjectMapper();
JavaTimeModule module = new JavaTimeModule();
// add my custom deserializer (this will affect all ZonedDateTime deserialization)
module.addDeserializer(ZonedDateTime.class, new CustomZonedDateTimeDeserializer());
objectMapper.registerModule(module);
如果你在 Spring 中配置它,配置将是这样的(未测试):
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean" id="pnxObjectMapper">
<property name="deserializersByType">
<map key-type="java.lang.Class">
<entry>
<key>
<value>java.time.ZonedDateTime</value>
</key>
<bean class="your.app.CustomZonedDateTimeDeserializer">
</bean>
</entry>
</map>
</property>
</bean>