Wrong column type in your table
I'm saving specific dateTime ex. 2023-01-01T12:00:00Z (this is Instant) to Postgresql Timestamp without timezone.
You have chosen the wrong data type for your column. The type TIMESTAMP WITHOUT TIME ZONE
cannot represent a moment, a specific point on the timeline. That type stores only a date with time-of-day, such as noon on Jan 23rd next year. But we have no way to know if that was meant to be noon in Tokyo, noon in Toulouse, or noon in Toledo — three very different moments, several hours apart.
The Z
at the end of your input string means an offset of zero hours-minutes-seconds from UTC. That, combined with a date and time, determines a moment.
To store that moment you need to define your column as TIMESTAMP WITH TIME ZONE
.
This has been covered many many times already on Stack Overflow, with many existing Answers including some written by me. Search to learn more such as using the Java type LocalDateTime
with one column type and OffsetDateTime
with the other column type.
If you use the correct type, all your problems will vanish. And the data stored in your database will be meaningful rather than ambiguous.
Writing:
OffsetDateTime odt = myInstant.atOffset( ZoneOffset.UTC ) ;
myPreparedStatement.setObject( … , odt ) ;
Reading:
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ; // Accessing a column of type TIMESTAMP WITH TIME ZONE.
Instant instant = odt.toInstant() ;
Your tools may lie to you
Understand that Postgres stores all TIMESTAMP WITH TIME ZONE
values with an offset from UTC of zero hours-minutes-seconds. Any zone or offset info submitted with an input is used to adjust that input to UTC.
So, values retrieved from a TIMESTAMP WITH TIME ZONE
column are always in UTC. However, middleware, drivers, and tooling may (unfortunately) choose to apply a zone or offset to retrieved values, thereby telling a lie.