Значение OffsetDateTime изменяется при извлечении из базы данных

Я использую таблицу из базы данных MS SQL и разработал GET API с помощью Spring Boot для извлечения всех данных из этой таблицы.
Здесь таблица содержит столбец типа datetimeoffset(7).

У меня есть член данных OffsetDateTime updatedDate внутри моей сущности, используемый для сопоставления столбца datetimeoffset из БД

Теперь, когда я получаю ответ API, я вижу, что значение updatedDate (2021-06-17T05:37:40.1938687+05:30) отличается от фактического значения базы данных (2021-06- 16 19:07:40.1938687 -05:00).

Я изучил Интернет, чтобы найти некоторую помощь, и попробовал несколько решений, похожих на Solution, однако я не увидел никаких положительных результатов.

Любая помощь будет действительно ценной, спасибо!

PS. Spring Boot версия: 2.3.1.RELEASE


person Vishal    schedule 09.07.2021    source источник


Ответы (2)


Эти два значения представляют одну и ту же точку на временной шкале. Они просто представлены в разных часовых поясах: база данных использует EST, а Spring приложение использует Индийский стандарт IST. Когда мы конвертируем их в GMT, они будут выглядеть одинаково:

String[] dates = {"2021-06-17T05:37:40.1938687 +05:30", "2021-06-16T19:07:40.1938687 -05:00"};
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.n XXX")
        .withZone(ZoneId.of("GMT"));
Arrays.stream(dates)
        .map(date -> formatter.format(OffsetDateTime.parse(date, formatter)))
        .forEach(System.out::println);

Над кодом печатается:

2021-06-17T00:07:40.1938687 Z
2021-06-17T00:07:40.1938687 Z

Если вы хотите сохранить исходное представление, вам нужно указать использовать часовой пояс EST вместо стандартного или системного. Попробуйте установить: spring.jackson.time-zone в файле конфигурации:

Часовой пояс, используемый при форматировании дат. Например, America/Los_Angeles или GMT+10.

person Michał Ziober    schedule 10.07.2021
comment
Спасибо за ответ. Я добавил свойство spring.jackson.time-zone в application.properties со значением GMT-5, однако результат все тот же. Нужно ли мне выполнять какие-либо другие дополнительные настройки, связанные с Джексоном, кроме сообщения title="дата часового пояса с весенней загрузкой и Джексоном"> stackoverflow.com/questions/46653455/ - person Vishal; 11.07.2021
comment
@Vishal, какую версию Jackson ты используешь? Вы создали свой собственный экземпляр ObjectMapper или используете общий, созданный Spring? Как это работает, когда вы создаете тестовый контроллер и возвращаете новый экземпляр OffsetDateTime? - person Michał Ziober; 11.07.2021
comment
Я использую Jackson версию как 2.11.0, и да, я предоставил настроенный экземпляр ObjectMapper, где я явно отключаю WRITE_DATES_AS_TIMESTAMPS и ADJUST_DATES_TO_CONTEXT_TIME_ZONE. Когда я возвращаю новый экземпляр OffsetDateTime, я вижу, что он имеет зону IST - person Vishal; 11.07.2021
comment
Привет, Михал, кстати, когда я отправляю экземпляр OffsetDateTime с другим ZoneOffset, я правильно вижу новую зону в ответе API. Например, OffsetDateTime now = OffsetDateTime.now(); now = now.withOffsetSameInstant(ZoneOddset.of("-05:30"); return now; мне нужно, чтобы Джексон сделал это за меня. - person Vishal; 11.07.2021
comment
@Vishal, попробуйте также проверить, как выглядит OffsetDateTime при загрузке из базы данных. Вы используете Hibernate или любой другой ORM? Взгляните на Hibernate неправильно сохраняет ZonedDateTime как datetimeoffset в SQL-сервер - person Michał Ziober; 11.07.2021
comment
даже после попытки выше, я все еще на той же странице - person Vishal; 13.07.2021

Теперь, когда я получаю ответ API, я вижу, что значение updatedDate (2021-06-17T05:37:40.1938687+05:30) отличается от фактического значения базы данных (2021-06-16 19:07:40.1938687 -05:00). ).

Нет, обе даты и времени представляют один и тот же момент/момент.

Демонстрация:

import java.time.Instant;

public class Main {
    public static void main(String[] args) {
        System.out.println(Instant.parse("2021-06-17T05:37:40.1938687+05:30"));
        System.out.println(Instant.parse("2021-06-16T19:07:40.1938687-05:00"));
    }
}

Вывод:

2021-06-17T00:07:40.193868700Z
2021-06-17T00:07:40.193868700Z

ОНЛАЙН-ДЕМО

Вы можете преобразовать одно в другое

Использование OffsetDateTime#withOffsetSameInstant< /a>, вы можете преобразовать одно в другое.

Демонстрация:

import java.time.OffsetDateTime;
import java.time.ZoneOffset;

public class Main {
    public static void main(String[] args) {
        OffsetDateTime odtFromResponse = OffsetDateTime.parse("2021-06-17T05:37:40.1938687+05:30");

        OffsetDateTime odtDesired = odtFromResponse.withOffsetSameInstant(ZoneOffset.of("-05:00"));
        System.out.println(odtDesired);
    }
}

Вывод:

2021-06-16T19:07:40.193868700-05:00

ОНЛАЙН-ДЕМО

Узнайте больше о современном API Date-Time на странице Trail: Date Time< /а>.

person Arvind Kumar Avinash    schedule 10.07.2021
comment
@Vishal - Попробуйте @JsonFormat(shape=JsonFormat.Shape.STRING, pattern="uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSXXX", timezone="America/Chicago") OffsetDateTime updatedDate и дайте мне знать, решило ли это вашу проблему. Измените часовой пояс в соответствии с часовым поясом вашего сервера БД. - person Arvind Kumar Avinash; 11.07.2021
comment
Привет, Арвинд, после внесения предложенных изменений я все еще вижу тот же часовой пояс. Нужно ли мне прекратить предоставление пользовательской реализации ObjectMapper? JFYI, член OffsetDateTime находится внутри @Entity, где я использовал аннотацию @JsonFormat. - person Vishal; 11.07.2021
comment
@Vishal - Из вашего другого комментария я заметил, что вы уже реализовали пользовательский ObjectMapper. Вы случайно не попробовали предложение в этот комментарий? - person Arvind Kumar Avinash; 11.07.2021
comment
Привет, Арвинд, я уже пробовал это, но не повезло. Одно из решений моей проблемы состоит в том, чтобы сделать часовой пояс JVM и часовой пояс БД одинаковыми. Например, используя аргумент JVM -Duser.timezone=US/Central. Это помогает решить эту проблему. Однако в моем случае я не хочу, чтобы приложение Spring Boot зависело от часового пояса базы данных. - person Vishal; 11.07.2021