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



我在postgresql数据库(引擎版本10.11(中有一个表,其中有一个名为resettime的列,其数据类型为timestamptz。数据库的默认时区是"0";澳大利亚/悉尼";。

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

我运行以下命令在DBEaver中设置此列。

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

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

在运行了上面的语句之后,我试图通过DBEaver中的以下语句来获取重置时间。

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

我应该如何确保我的scala应用程序也获得与我通过DBEaver访问相同的行为?在上面的例子中,我希望我的scala应用程序不会为了运行相同的update语句而更改resettime。谢谢

问题是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;

你想干什么就干什么。

最新更新