如何将OffsetDateTime存储到PostgreSQL“带时区的时间戳”列

san*_*nny 0 java postgresql jdbc timestamp-with-timezone java-time

我正在尝试OffsetDateTime("2019-01-14 21:10:00.02+03")使用JDBC与PostgreSQL 一起存储时区(+03)。但是,当使用sql查询检索数据时,我总是得到+00结果。有什么方法可以在postgres中使用datetime存储偏移量(+03)吗?

And*_*eas 7

Postgres 以 UTC 存储所有内容,并且不保留原始时区。

with timezone只是意味着该值将为您转换为会话时区,这在 JDBC 上下文中毫无意义,因此您始终获得 UTC 格式的值。

如果您需要存储时区偏移量,那么您需要自己将其存储在单独的列中。


Gor*_*son 7

有什么方法可以在postgres中使用datetime存储偏移量(+03)吗?

是的,但是正如@Andreas所说,偏移量必须在单独的列中。timestamp with time zonePostgreSQL中的列类型名称有点误导;真的只是timestamp converted to utc。原始偏移与时间戳值一起存储。

现在,您可能会想添加一个新varchar列并将偏移量保存为hh:mm字符串,例如,

id  twtz                    twtz_offset
--  ----------------------  -----------
 1  2019-01-15 07:00:00+00  -07:00
Run Code Online (Sandbox Code Playgroud)

但实际上,最好使用秒数提取偏移量ZoneOffset#getTotalSeconds()并将其存储在integer列中,例如,

id  twtz                    twtz_offset
--  ----------------------  -----------
 1  2019-01-15 07:00:00+00       -25200
Run Code Online (Sandbox Code Playgroud)

因为该数字可以直接应用于UTC值以转换回原始值,OffsetDateTime而不必将偏移量转换Stringint

OffsetDateTime odtRetrieved = rs.getObject("twtz", OffsetDateTime.class);  // always UTC for PostgreSQL
// odtRetrieved is 2019-01-15T07:00Z
OffsetDateTime odtOriginal = odtRetrieved
        .toInstant()
        .atOffset(ZoneOffset.ofTotalSeconds(rs.getInt("twtz_offset")));
// odtOriginal is 2019-01-15T00:00-07:00
Run Code Online (Sandbox Code Playgroud)

并且还提供了一些额外的鲁棒性,以防万一您发现自己实际上不是一整分钟的怪异偏移。

(如果您认为这将永远不会发生,那么请留意乔恩·斯基特即将出版的科技/恐怖小说《时区规则几乎打动了我的大脑》。基于真实的故事。很快将在书店中出售。)