postgresql Дата против Java Мгновенное действие - PullRequest
0 голосов
/ 21 февраля 2019

Предположим, у меня есть поле в приложении Java типа Instant и я храню его в базе данных PostgreSQL как тип DATE.

Если я сохраню, например, 21.02.2019 14:03:59, оно будетбудет храниться как 21.02.2019, но как он будет переведен при чтении из базы данных?

Будет ли это:

  • 21.02.2019 00:00:00.000 или
  • 21.02.2019 23:59:59.000?

PS.Я знаю, что я должен использовать Timestamp вместо:)

Ответы [ 2 ]

0 голосов
/ 21 февраля 2019

tl; dr

  • A DATE столбец в базе данных, соответствующей стандарту SQL, такой как Postgres, хранит только дату, время и зону.
  • Используйте LocalDate для значения только для даты, без времени и зоны.
  • Чтобы получить LocalDate из Instant, укажите время настенных часов, используемое людьмиопределенного региона (часового пояса), по которому вы хотите определить дату.
  • Если вы хотите сохранить момент (представленный объектом Instant), используйте стандартный тип SQL TIMESTAMP WITH TIME ZONE вместо DATE.

Подробности

Instant в UTC

Объект Instant представляет момент в UTC , всегда в UTC.Другими словами, момент с смещением от UTC равен нулю часов-минут-секунд.

Для определения даты требуется часовой пояс

Получение даты из *Поэтому для 1034 * требуется часовой пояс (ZoneId).Момент после полуночи в Париже Франция - это новая дата, скажем, 23 , в то время как в Монреале-Квебеке она все еще «вчера» 22-го .В любой момент времени дата меняется по всему земному шару в зависимости от зоны.

Поэтому, если вы имели в виду дату, показанную в Квебеке, укажите часовой пояс "Америка / Монреаль".

ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;

Вы сказали, что столбец вашей базы данных имеет тип DATE. В Postgres, как и в стандарте SQL, это означает значение только для даты, без времени суток и без часового пояса.

Чтобы сохранить только дату, без времени суток и без часового пояса, извлеките LocalDate. Слово «местный» означает любой населенный пункт или все населенных пунктов, но не какой-либо одной конкретной местности.

LocalDate ld = zdt.toLocalDate() ;

JDBC 4.2

Обменяйте LocalDate через заполнитель в подготовленном выражении.

myPreparedStatement.setObject( … , ld ) ; 

Извлечение:

LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;

Дата сохранена, дата извлечена

как она будет переведена снова, когда я буду читать из базы данных?

Будет ли этобыть:

21.02.2019 00: 00: 00.000 или…

Этот вопрос не имеет смысла. Когда вы читаете DATE с SQL-стендаArd-совместимая база данных, такая как Postgres, вы получаете дату, только дату - без времени и без часового пояса.

Если вы храните LocalDate значения 2019-02-21 в DATEстолбец, вы получите то же самое: a LocalDate значения 2019-02-21.

Первый момент дня

Если вы хотите добавить время дня для первого моментадня, пусть java.time определит это для вас.В некоторые даты в некоторых часовых поясах день не начинается в 00:00:00, а может начинаться в 01:00: 00.

LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;
ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime zdt = ld.atStartOfDay( z ) ;  // Returns a `ZonedDateTime` object set to the first moment of the day as seen on that date in that time zone. May or may not be the time 00:00:00. 

UTC

Если вы хотите извлечь дату из вашего Instant, используя UTC в качестве часового пояса, что означает смещение от UTC, равное нулю часов, минут и секунд, используйте класс OffsetDateTime с константой * 1106.*ZoneOffset.UTC.

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

О java.time

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

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

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

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

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

  • Java SE 8 , Java SE 9 , Java SE 10, Java SE 11 и более поздних версий - часть стандартного Java API с связанной реализацией.
    • Java 9 adНекоторые незначительные функции и исправления.
  • Java SE 6 и Java SE 7
    • Большинство функций java.time перенесены в Java 6 & 7 в ThreeTen-Backport .
  • Android
    • Более поздние версии реализации пакета Android для классов java.time .
    • Для более ранних версий Android (<26) проект <a href="https://github.com/JakeWharton/ThreeTenABP" rel="nofollow noreferrer"> ThreeTenABP адаптируется ThreeTen-Backport (упомянуто выше).См. Как использовать ThreeTenABP… .

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

0 голосов
/ 21 февраля 2019

Это зависит от того, как вы читаете это.Instant и SQL DATE не эквивалентны, и я не знаю ни одной надежной библиотеки, которая позволяла бы вам читать DATE до Instant.Если вы пишете свой собственный код, который позволяет это, тогда вы можете заставить его заполнять часы, минуты, секунды и миллисекунды любым удобным для вас способом, даже если это не имеет смысла (поэтому реальный ответ на ваш вопрос будет "ни "если вы явно не напишете код для преобразования java.sql.Date в java.time.Instant).

Если вы разрабатываете программное обеспечение, которое хранит моменты времени как даты, то ваш дизайн имеет недостатки.Либо используйте LocalDate на стороне Java, либо TIMESTAMP в базе данных.

...