Получить дату из DataObject (SDO), не теряя часа (JAVA) - PullRequest
1 голос
/ 22 мая 2019

Я пытаюсь получить дату из объекта DataObject ( Объект даты обслуживания (SDO) ), который приходит ко мне в качестве входных данных, и вставить его в базу данных Oracle. Проблема заключалась в том, что дата, которую я получаю, похоже, не имеет введенного часа.

Я использую метод setDate () из DataObject со следующим значением: 2019-05-22T13: 30: 00Z.

Почему-то при использовании getDate () возвращается день, введенный с часом, установленным в 0 (2019-05-22 00:00:00).

Я не уверен, связано ли это с форматом ввода или чем-то связанным с классом Date из java.utils.

Простым решением было бы передать его как String и преобразовать в Date, используя формат, но я бы хотел сохранить этот промежуточный шаг.

1 Ответ

2 голосов
/ 22 мая 2019

java.util.Date против java.sql.Date

Ваш вопрос не содержит достаточно подробностей, чтобы знать наверняка, но я могу сделать обоснованное предположение.

возврат - это день, введенный с часом, установленным на 0 (2019-05-22 00:00:00).

Я подозреваю, что ваш код, вызывающий setDate и / или getDate, использует объект java.sql.Date вместо объекта java.util.Date.

Проверьте свои import утверждения. Если вы случайно использовали неправильный класс, это объяснило бы, что время суток устанавливается на 00: 00.

  • java.util.Date представляет момент в UTC (дата, время суток и смещение от UTC, равное нулю часов, минут и секунд).
  • java.sql.Date делает вид, что представляет только дату, без времени суток и без часового пояса или смещения от UTC. На самом деле содержит с указанием времени суток и смещения, но пытается настроить время на 00: 00: 00.0 как часть притворства.

Смешение? Да. Эти старые классы даты и времени с самых ранних дней Java представляют собой чертовски ужасный беспорядок, созданный людьми, которые не понимали сложностей обработки даты и времени. Избегайте этих устаревших классов даты и времени!

Эти устаревшие классы были вытеснены несколько лет назад современными java.time классами, определенными в JSR 310. Попробуйте выполнить всю свою работу в java.time . При взаимодействии со старым кодом, таким как SDO, который еще не обновлен для java.time , вызовите новые методы преобразования, добавленные к старым классам.

Современная замена java.util.Date составляет java.time.Instant. Оба представляют момент в UTC, хотя Instant имеет лучшее разрешение наносекунд по сравнению с миллисекундами.

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

Преобразование из современного класса в унаследованный класс. Остерегайтесь потери данных: любые микросекунды или наносекунды за доли секунды усекаются до миллисекунд (как указано выше).

java.util.Date d = java.util.Date.from( instant ) ;  // Convert from modern to legacy. Truncates any microseconds or nanoseconds.

Перейдите к вашему объекту SDO.

mySdoDataObject.setDate( d ) ;

Идя в другом направлении, найдите устаревший объект java.util.Date и немедленно преобразуйте в Instant.

Instant instant = mySdoDataObject.getDate().toInstant() ;  

Чтобы увидеть тот же момент через часы настенного времени, используемые людьми определенного региона (часового пояса), примените ZoneId, чтобы получить ZonedDateTime объект.

ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;  // Same moment, same point on the timeline, different wall-clock time.

Простым решением было бы передать его как String

Нет! Используйте смарт-объекты, а не тупые строки. У нас есть ведущая в отрасли библиотека даты и времени, встроенная в Java, поэтому используйте ее.

База данных

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

Table of date-time types for Java (both legacy & modern) and for standard SQL.

Ваш драйвер JDBC может дополнительно обрабатывать Instant. Если нет, конвертируйте в OffsetDateTime.

OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
myPreparedStatement.setObject( … , odt ) ;

индексирование.

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

О java.time

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

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

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

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

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

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

...