Postgres: “AT TIME ZONE 'localtime'” 是否等同于 “AT TIME ZONE 'utc'”?

7
我很难理解"AT TIME ZONE 'localtime'"的确切工作方式。通过尝试,我发现它的作用与"AT TIME ZONE 'UTC'"完全相同...但是为什么呢?在 postgres 中,"localtime""UTC"的同义词吗?还是来自某些设置(环境?连接时区?虽然都已检查过,但似乎它们之间没有关联)...
这里有一个"localtime"函数,但我认为它与此无关。
示例 SQLs:
# date
Thu Dec  8 12:00:05 AEDT 2016

# SELECT LOCALTIMESTAMP;
----------------------------
 2016-12-08 01:13:29.444725

# SELECT LOCALTIMESTAMP AT TIME ZONE 'America/New_York';
-------------------------------
 2016-12-08 06:08:31.183103+00

# SELECT LOCALTIMESTAMP AT TIME ZONE'localtime';
------------------------------
 2016-12-08 01:09:25.294063+00

# SELECT LOCALTIMESTAMP AT TIME ZONE 'utc';
 -------------------------------
 2016-12-08 01:09:44.32587+00 -- SAME AS ABOVE

 # SET TIME ZONE 'America/New_York';

 # SELECT LOCALTIMESTAMP;
 ----------------------------
  2016-12-07 20:13:34.924647

 # SELECT LOCALTIMESTAMP AT TIME ZONE 'localtime';
 ------------------------------
  2016-12-07 15:10:08.188197-05

 # SELECT LOCALTIMESTAMP AT TIME ZONE 'utc';
 ------------------------------
  2016-12-07 15:10:44.88332-05 -- SAME AS ABOVE

有什么提示吗?有没有相关文档记录?

1
像这样的问题必须提供正在使用的Postgres版本。同样相关的是:服务器操作系统和时区设置,以及在使用SET TIME ZONE之前通过SHOW timezone获得的内容。您是否有非默认的timezone_abbreviations设置? - Erwin Brandstetter
1个回答

8
在Postgres中,时间戳实际上不存储任何时区信息。相反,这些信息来自于服务器设置的时区。内部上,所有时间戳信息都是以UTC时间记录的。因此,例如,如果您从UTC之外的时区存储时间戳信息,则Postgres会在存储之前将该时间戳转换为UTC。
根据文档
对于带有时区的时间戳,内部存储的值始终为UTC(协调世界时,传统上称为格林威治标准时间GMT)。具有显式时区的输入值使用该时区的适当偏移量转换为UTC。如果输入字符串中未指定时区,则假定它在系统时区参数指示的时区中,并使用时区区域的偏移量将其转换为UTC。
至于您实际的问题,localtime只是服务器的时区,始终为UTC。
此外,似乎Postgres的localtime只是封装了C库函数localtime(),该函数试图找到本地系统时间(默认为UTC时间)。再次引用文档中的内容:

如果在postgresql.conf中或作为服务器命令行选项中未指定时区,则服务器将尝试使用TZ环境变量的值作为默认时区。如果未定义TZ或不是PostgreSQL已知的任何时区名称,则服务器通过检查C库函数localtime()的行为来确定操作系统的默认时区。默认时区是从PostgreSQL已知的时区中选择最接近的匹配项。(如果未指定,则这些规则也用于选择log_timezone的默认值。)


1
谢谢您的回复。不过,这个在哪里有记录呢?我能改变它吗?我只是想了解所有的细节。 - stillwaiting
@stillwaiting 看起来Postgres的locatime只是包装了C库函数localtime(),该函数获取本地UTC系统时间。因此可能无法更改此设置。如果在Postgres中指定时区,则会使用该时区。 - Tim Biegeleisen
请注意,尽管 timestamp 类型不存储时区信息,但 timestamptz 类型会存储。使用 timestamptz 可能比 timestamp 更少出错,因为任何给定的时间戳都可以在时区之间正确转换。特别是当时间戳是在运行代码的时区与数据库不同时生成的时,这一点尤其正确。 - karmakaze

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接