postgresql Дата против Java Мгновенное действие
Предположим, у меня есть поле в приложении 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 ответа
ТЛ; др
-
DATE
Столбец в базе данных, соответствующей стандарту SQL, такой как Postgres, хранит только дату, время и зону. - использование
LocalDate
для значения только для даты, без времени и зоны. - Чтобы получить
LocalDate
изInstant
укажите время на часах, используемое людьми определенного региона (часового пояса), по которым вы хотите определить дату. - Если вы хотите сохранить момент (как представлено
Instant
объект), используйте тип стандарта SQLTIMESTAMP WITH TIME ZONE
скорее, чемDATE
,
подробности
Instant
в UTC
Instant
Объект представляет момент в UTC, всегда в UTC. Другими словами, момент со смещением от UTC, равным нулю, часам, минутам и секундам.
Для определения даты требуется часовой пояс
Получение даты от Instant
поэтому требуется часовой пояс (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, такой как Postgres, вы получаете дату, только дату - без времени и без часового пояса.
Если вы храните LocalDate
стоимости 2019-02-21
в DATE
столбец, вы получите то же самое: 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.
универсальное глобальное время
Если вы хотите извлечь дату из вашего Instant
используя UTC в качестве часового пояса, то есть смещение от UTC, равное нулю часов, минут и секунд, используйте OffsetDateTime
класс с константой ZoneOffset.UTC
,
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
LocalDate ld = odt.toLocalDate() ;
myPreparedStatement.setObject( … , ld ) ;
О java.time
Инфраструктура java.time встроена в 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 и более поздние версии - часть стандартного API Java со встроенной реализацией.
- Java 9 добавляет некоторые незначительные функции и исправления.
- Java SE 6 и Java SE 7
- Большая часть функциональности java.time перенесена на Java 6 и 7 в ThreeTen-Backport.
- Android
- Более поздние версии Android связывают реализации классов java.time.
- Для более ранних версий Android (<26) проект ThreeTenABP адаптирует ThreeTen-Backport (упомянутый выше). Смотрите Как использовать ThreeTenABP….
Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Вы можете найти некоторые полезные классы здесь, такие как Interval
, YearWeek
, YearQuarter
и многое другое.
Это зависит от того, как вы читаете это. Instant
и SQL DATE
не эквивалентны, и я не знаю ни одной надежной библиотеки, которая позволила бы вам читать DATE
в Instant
, Если вы пишете свой собственный код, который позволяет это, тогда вы можете заставить его заполнять часы, минуты, секунды и миллисекунды любым удобным для вас способом, даже если это не имеет смысла (поэтому реальный ответ на ваш вопрос будет " ни ", если вы явно не пишете код для преобразования java.sql.Date
в java.time.Instant
).
Если вы разрабатываете программное обеспечение, которое хранит моменты как даты, значит, ваш дизайн имеет недостатки. Либо использовать LocalDate
на стороне Java, или TIMESTAMP
в базе данных.