使用分区时间将字符串转换为 LocalDateTime
Convert String to LocalDateTime with zoned time
我在主题中收到了一个带有日期和偏移量的字符串字段,我需要通过添加偏移量将此字符串转换为 LocalDateTime。例如,如果我收到:
2021-07-20T19:00:00.000+02:00
我想在 LocalDateTime 中转换:
2021-07-20T21:00:00.000
为此,我有一个带有自定义对象映射器的 Bean:
@Configuration
public class MyConfiguration {
@Bean
public MyCustomObjectMapper configure() {
final ObjectMapper mapper = new ObjectMapper();
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX");
final LocalDateTimeDeserializer dateTimeDeserializer = new LocalDateTimeDeserializer(formatter);
final LocalDateTimeSerializer dateTimeSerializer = new LocalDateTimeSerializer(formatter);
final JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addDeserializer(LocalDateTime.class, dateTimeDeserializer);
javaTimeModule.addSerializer(LocalDateTime.class, dateTimeSerializer);
mapper.registerModule(javaTimeModule);
return new MyCustomObjectMapper (mapper);
}
}
但它并没有像我预期的那样工作,因为生成的 LocalDateTime 偏移量消失了并且没有被添加:
2021-07-20T19:00:00.000
我怎样才能实现这个目标?
LocalDateTime
class 是一种 date-time 表示,它不知道时区,LocalDateTimeDeserializer
忽略源数据中的任何时区信息是合乎逻辑的.
要考虑时区,您可以使用 InstantDeserializer.OFFSET_DATE_TIME
反序列化器(DateTimeFormatter.ISO_OFFSET_DATE_TIME
实际上是您拥有的源日期时间的格式)并将其结果转换为 LocalDateTime
在所需区域内。这可以包装在自定义反序列化器中以便于使用,例如
class SmartLocalDateTimeDeserializer extends StdDeserializer<LocalDateTime> {
private final InstantDeserializer<OffsetDateTime> delegate = InstantDeserializer.OFFSET_DATE_TIME;
public SmartLocalDateTimeDeserializer() {
super(LocalDateTime.class);
}
@Override
public LocalDateTime deserialize(JsonParser p,
DeserializationContext ctxt) throws IOException, JsonProcessingException {
final OffsetDateTime result = delegate.deserialize(p, ctxt);
return result.atZoneSameInstant(ZoneId.systemDefault()).toLocalDateTime();
}
}
...
javaTimeModule.addDeserializer(LocalDateTime.class, new SmartLocalDateTimeDeserializer());
我在主题中收到了一个带有日期和偏移量的字符串字段,我需要通过添加偏移量将此字符串转换为 LocalDateTime。例如,如果我收到:
2021-07-20T19:00:00.000+02:00
我想在 LocalDateTime 中转换:
2021-07-20T21:00:00.000
为此,我有一个带有自定义对象映射器的 Bean:
@Configuration
public class MyConfiguration {
@Bean
public MyCustomObjectMapper configure() {
final ObjectMapper mapper = new ObjectMapper();
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX");
final LocalDateTimeDeserializer dateTimeDeserializer = new LocalDateTimeDeserializer(formatter);
final LocalDateTimeSerializer dateTimeSerializer = new LocalDateTimeSerializer(formatter);
final JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addDeserializer(LocalDateTime.class, dateTimeDeserializer);
javaTimeModule.addSerializer(LocalDateTime.class, dateTimeSerializer);
mapper.registerModule(javaTimeModule);
return new MyCustomObjectMapper (mapper);
}
}
但它并没有像我预期的那样工作,因为生成的 LocalDateTime 偏移量消失了并且没有被添加:
2021-07-20T19:00:00.000
我怎样才能实现这个目标?
LocalDateTime
class 是一种 date-time 表示,它不知道时区,LocalDateTimeDeserializer
忽略源数据中的任何时区信息是合乎逻辑的.
要考虑时区,您可以使用 InstantDeserializer.OFFSET_DATE_TIME
反序列化器(DateTimeFormatter.ISO_OFFSET_DATE_TIME
实际上是您拥有的源日期时间的格式)并将其结果转换为 LocalDateTime
在所需区域内。这可以包装在自定义反序列化器中以便于使用,例如
class SmartLocalDateTimeDeserializer extends StdDeserializer<LocalDateTime> {
private final InstantDeserializer<OffsetDateTime> delegate = InstantDeserializer.OFFSET_DATE_TIME;
public SmartLocalDateTimeDeserializer() {
super(LocalDateTime.class);
}
@Override
public LocalDateTime deserialize(JsonParser p,
DeserializationContext ctxt) throws IOException, JsonProcessingException {
final OffsetDateTime result = delegate.deserialize(p, ctxt);
return result.atZoneSameInstant(ZoneId.systemDefault()).toLocalDateTime();
}
}
...
javaTimeModule.addDeserializer(LocalDateTime.class, new SmartLocalDateTimeDeserializer());