История с поддержкой JSR-310
и JDBC 4.2
в СУБД и драйверах такова, что на самом деле творится что-то непонятное и это непонятное постоянно причиняет уйму боли.
I. "Официальное" название типа данных "timestamp with time zone" в СУБД на самом деле не отражает действительность, на самом деле именно часовой пояс СУБД в соответствующих полях не хранят, причина этому довольно прозаична: чтобы уметь быстро сравнивать даты со временем нужно уметь их быстро преобразовывать из одного часового пояса в другой, в то же время часовым поясам свойственно меняться: какие-то разделяются, какие-то, наоборот схлопываются, где-то вводят переход на летнее время, где-то наоборот отменяют, поэтому СУБД используют два типичных подхода для хранения "timestamp with time zone":
- всегда хранить в UTC (PostgreSQL, Oracle)
- хранить информацию о смещении (! речь не про часовой пояс, а про смещение) относительно UTC (MSSQL)
II. какой тип данных для "дат со временем" использовать в СУБД, это в большинстве случаев выбор разработчика, однако, здесь следует понимать, что универсального решения не существует, например с хранением "дат со временем" приведенных к UTC существует некоторая проблема, связанная с тем, что будущее не определено и если в данный момент времени мы в считаем, что полночь '1 января 2024 по Москве' соответствует '9 вечера 31 декабря 2023 по UTC', то завтра или через полгода это уже может быть совсем не так, т.е. если мы решили хранить в БД "даты со временем" используя тип "timestamp with time zone", то нужно быть готовым к тому, что рано или поздно нам придется данные в СУБД перебивать. Здесь в изначальном вопросе имеет место быть определенная странность: "имеются колонки с типом TIMESTAMPZ" - на мой взгляд, СУБД где одновременно используются типы "timestamp without time zone" и "timestamp with time zone" без дополнительных конвенций по наименованию - это не база данных, а помойка: нужно или везде иметь одинаковые типы данных, или каким-то образом помечать особенности хранения данных посредством наименования полей, чтобы не приходилось каждый раз лезть в структуру БД для понимания правильно ли я работаю с данными.
III. Какой именно тип использовать в жаве - на самом деле вопрос филосовский и очень много зависит от используемого фреймворка, например, хибернейт поддерживает работу и с Instant
, и с ZonedDateTime
, и с LocalDateTime
вне зависимости от того что написано в спецификации JDBC 4.2
- у разработчиков соответствующего фреймворка так или иначе существует цель привлечь как можно больше пользователей. Если же дело касается "чистого" JDBC, то тут единственный вариант - вдумчиво читать спецификацию, оценивать последствия и принимать решения, например, ранее уже упомянули, что для timestamptz
в PostgreSQL
нужно либо использовать "современный" OffsetDateTime
либо устаревшие типы Timestamp
, Date
, Calendar
(здесь на самом деле разработчики драйвера PostgreSQL
подложили свинью: для старых типов Java
все работает вполне "ожидаемо", а в случае "современных" типов грабли разложены весьма предусмотрительно, в других СУБД все совсем иначе, аналогично только в PostgreSQL
нельзя тип БД date
в LocalDateTime
)