Postgres:"在时区'当地时间' =="在时区' utc'"?

时间:2016-12-08 01:15:59

标签: postgresql time timezone

我很难理解"AT TIME ZONE 'localtime'"究竟是如何运作的?通过玩它,我发现它的行为与"AT TIME ZONE 'UTC'"完全相同......但为什么呢? "localtime"是postgres中"UTC"的同义词吗?或者它来自某些设置(环境?连接时区?虽然检查了两者,似乎它们没有关系)...

"localtime" function,但我认为这里没有涉及。

示例SQL:

# 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 个答案:

答案 0 :(得分:5)

Postgres中的时间戳实际上并不存储任何时区信息。相反,此信息来自服务器设置的时区。在内部,所有时间戳信息都以UTC时间记录。因此,例如,如果您从UTC以外的时区存储时间戳信息,Postgres会先将该时间戳转换为UTC,然后再存储。

来自documentation

  

对于带时区的时间戳,内部存储的值始终为UTC(通用协调时间,传统上称为格林威治标准时间,GMT)。具有指定显式时区的输入值将使用该时区的适当偏移量转换为UTC。如果输入字符串中没有声明时区,则假定它位于系统时区参数指示的时区内,并使用时区的偏移量转换为UTC。

对于您的实际问题,localtime只是服务器的时区,始终是UTC。

此外,看来Postgres' localtime只包装C库函数localtime(),它试图找到本地系统时间(默认为UTC时间)。同样,来自documentation

  

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