Преобразование строки в LocalDateTime с зональным временем

Я получил поле String в теме с датой и смещением, и мне нужно преобразовать эту строку в 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 и включить любые аннотации, которые у вас есть в поле?

blacktide 06.05.2022 16:23
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Версия Java на основе версии загрузки
Версия Java на основе версии загрузки
Если вы зайдете на официальный сайт Spring Boot , там представлен start.spring.io , который упрощает создание проектов Spring Boot, как показано ниже.
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
0
1
37
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Класс LocalDateTime представляет собой представление даты и времени, которое не знает о часовых поясах, и вполне логично, что LocalDateTimeDeserializer игнорирует любую информацию о часовом поясе в исходных данных.

Чтобы учесть часовой пояс, вы можете использовать десериализатор InstantDeserializer.OFFSET_DATE_TIME (на самом деле это формат исходной даты и времени, который у вас есть) и преобразовать его результат в DateTimeFormatter.ISO_OFFSET_DATE_TIME в нужной зоне. Это может быть обернуто в пользовательский десериализатор для простоты использования, например.

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());

Другие вопросы по теме