Выбор даты UTC в Oracle и преобразование в UTC в Java

2

Если я позвоню в свое приложение:

System.currentTimeMillis()

результат будет, скажем: 1536842771599, то есть: GMT: четверг, 13 сентября 2018 г. 12: 46: 11.599 PM ИЛИ в моем местном офисе: четверг, 13 сентября 2018 г. 3: 46: 11.599 PM GMT + 03: 00 DST

Если я сделаю следующий выбор в базе данных Oracle, установленной локально:

select CAST(sys_extract_utc(SYSTIMESTAMP) AS DATE) from dual;

Я получаю через следующий код JdbcTemplate:

jdbc.queryForObject(sqlCommand, new Object[0], Timestamp.class);

следующий результат: Изображение 174551

Что, на мой взгляд, уже неверно, потому что Timestamp обычно представляет собой локализованное время. Кроме того, если я позвоню:

myResult.getTime()

чтобы получить длинную стоимость, это изменит мое время, которое было около 12.46 вечера, до значения 1536831971599, что на самом деле: GMT: четверг, 13 сентября 2018 года, 9: 46: 11.599.

Очевидно, что это плохо, потому что за моим фактическим местным временем это 2 * GMT + 03: 00 (6 часов), а GMT + 03: 00 (3 часа) за временем UTC базы данных.

Что я делаю неправильно? Мой единственный вывод до сих пор заключается в том, чтобы избежать использования sys_extract_utc в базе данных и позволить базе данных вернуть мне локальное время, которое будет преобразовано в UTC, когда я вызову getTime в экземпляре Timestamp.

Любое объяснение этому?

PS Основа на ответе, что java.sql.Timestamp - это UTC, я добавляю скриншот того, что показывает отладчик, и что неправильно, потому что он считает, что результат UTC - GMT + 03: 00. Таким образом, это показывает мое время как 8.26 + 03:00. Мое время - 11.26. Если я вызову getTime в этом экземпляре Timestamp, я получу длинное значение, которое, если я положу https://www.epochconverter.com/, тогда я получу пятницу, 14 сентября 2018 г. 8:26:06 GMT + 03: 00 DST или пятница, 14 сентября 2018 года 5:26:06, что составляет ровно 3 часа позади того, что у меня на самом деле есть как UTC!

PS2 Я использую Spring JDBC 4.2.5-RELEASE. Невозможно использовать Instant с ним, он выдает исключение, которое не может преобразовать Timestamp в Instant, потому что оно ожидает что-то, что происходит от Number. К сожалению, я не могу изменить этот JDBC, даже версия.

Изображение 174551

Теги:
spring
timestamp
jdbctemplate

1 ответ

4

ТЛ; др

Вы не понимаете класс java.sql.Timestamp.

  • java.sql.Timestamp всегда представляет момент в UTC.
  • java.time.Instant лет назад заменил Timestamp.

Используйте только Instant, никогда не Timestamp.

Instant

Страшный класс java.sql.Timestamp теперь устарел с помощью классов java.time, в частности Instant.

Instant.now()  // Capture the current moment in UTC. 

JDBC 4.2

Начиная с JDBC 4.2, мы можем напрямую обменивать объекты java.time с базой данных. Не нужно снова использовать ужасные классы Date, Calendar или java.sql.

Загрузить.

Instant instant = myResultSet.getObject( … , Instant.class ) ;

Вставить.

myPreparedStatement.setObject( … , instant ) ;

Временная метка обычно представляет собой локализованное время.

Неправильно. java.sql.Timestamp представляет момент в UTC, всегда UTC, по определению. Аналогично, Instant также представляет момент в UTC. Оба класса представляют собой счет с первого момента 1970 года в UTC.


О java.time

Рамка java.time встроена в Java 8 и более поздние версии. Эти классы вытесняют неприятные старые устаревшие классы времени, такие как java.util.Date, Calendar и SimpleDateFormat.

Проект Joda-Time, теперь в режиме обслуживания, советует перейти на классы java.time.

Чтобы узнать больше, ознакомьтесь с учебным пособием Oracle. И поиск Qaru для многих примеров и объяснений. Спецификация - JSR 310.

Вы можете обменивать объекты java.time непосредственно с вашей базой данных. Используйте JDBC-драйвер, совместимый с JDBC 4.2 или новее. Нет необходимости в строках, нет необходимости в java.sql.*.

Где можно получить классы java.time?

Проект ThreeTen-Extra расширяет java.time с дополнительными классами. Этот проект является доказательством возможных будущих дополнений к java.time. Здесь вы можете найти полезные классы, такие как Interval, YearWeek, YearQuarter и другие.

  • 0
    Спасибо за такое подробное объяснение! Тем не менее, я не понимаю, почему после выполнения Oracle SQL, который я написал выше, в конструкторе Timestamp приходит значение 1536831971599 вместо 1536842771599. На основе документации System.currentTimeMillis () возвращает UTC, и я также выбираю из Oracle UTC , Почему значения отличаются точно моим часовым поясом, то есть GMT + 03: 00?
  • 0
    Я обновил вопрос, возможно, это прояснит мою путаницу. Спасибо!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню