通过客户端和 DBeaver 访问 PostgreSQL 的时区

Time zone for PostgreSQL by accessing through client and DBeaver

我在 postgresql 数据库(引擎版本 10.11)中有一个 table,其中有一个名为 resettime 的列,其数据类型为 timestamptz。数据库的默认时区是“Australia/Sydney”。

重置时间列的默认值为时区('UTC'::text, now())。

我运行下面的命令在DBEaver中设置这个列。

update mytable set resettime = timezone('UTC', now()) + interval '1 hour' where id = 1;

当前UTC时间为11:47,对应AEST时间为21:47

在运行上面的语句之后,我尝试在DBEaver中通过下面的语句来获取resettime。

select resettime from mytable where id=1

从这个语句中,我得到了2020-09-14 12:47:25

然后,我运行在DBEaver中执行以下命令。

update mytable set resettime = resettime + interval '1 hour' where resettime < timezone('UTC', now());

在运行这个命令之后,我检查了id=1记录的重置时间,我发现重置时间和我预期的一样。很正常。

然而,当我在我的 scala 应用程序中 运行 相同的更新语句时,它将重置时间更新为 2020-09-14 13:47:25。我有一种感觉,如果我通过我的 scala 应用程序访问 resettime,它仍然被视为 AEST 时间。我不想将默认时区设置更改为 UTC。

我应该如何确保我的 Scala 应用程序也获得与通过 DBEaver 访问相同的行为?在上面的示例中,我希望我的 scala 应用程序不会将重置时间更改为 运行 相同的更新语句。谢谢!

问题是 timezone('UTC', now()) 将当前时间戳转换为 timestamp without time zone – 结果是当前时间戳,就像在设置为 UTC 时间的时钟上看起来的那样。

然后,当你将结果赋值给resettime时,它是一个timestamp with time zone,它转换回来的值,但是这次是根据你当前设置的timezome参数(与 UTC 不同)。

因此,您首先询问 UTC 时钟现在看起来如何,然后您在当前时区解释该结果。因此,您最终得到一个偏移值。

简单而正确的解决方案是根本不在两种时间戳类型之间进行转换,而是坚持使用timestamp with time zone:

update mytable
set resettime = now() + interval '1 hour'
where id = 1;

这就是你想要的。