postgresql timezone conversion'EST'!=' - 05'

时间:2017-12-28 19:13:05

标签: sql postgresql postgresql-9.6

我在x86_64-pc-linux-gnu上运行PostgreSQL 9.6.6,我的时区设置为'UTC'。

有谁知道为什么以下SELECT陈述的结果不同?

A)

SELECT timezone('EST', '2017-12-21');
    timezone       
---------------------
2017-12-20 19:00:00

B)

SELECT timezone('-05', '2017-12-21');
      timezone       
---------------------
2017-12-21 05:00:00

根据pg_timezone_names-05应该与EST具有相同的偏移...有什么想法吗?感谢。

2 个答案:

答案 0 :(得分:2)

https://www.postgresql.org/docs/current/static/view-pg-timezone-names.html

  

视图pg_timezone_names提供了时区名称列表   由SET TIMEZONE识别

并进一步:

  

utc_offset interval UTC的偏移量(正值表示格林威治以东)

当你set timezone to 'EST'时 - 你声明你的客户是在EST时区,因此返回的时间将根据你的tz进行调整:

t=# select '2017-12-21'::timestamptz;
      timestamptz
------------------------
 2017-12-21 00:00:00-05
(1 row)

区间匹配来自pg_timezone_names和isequal -05的utc_offset,因此它按预期工作。 (如果你set timezone to '-05',确实在EST中将比UTC少5小时。

-05EST都为SET TIMEZONE提供了相同的结果,如文档中所述。

现在,您使用intervalhttps://www.postgresql.org/docs/current/static/functions-datetime.html#FUNCTIONS-DATETIME-ZONECONVERT

回答与文档的协调
  

在这些表达式中,可以指定所需的时区区域   或者作为文本字符串(例如,'PST')或作为间隔(例如,   INTERVAL'-08:00')。

遵循这些规则也可以:

t=# select '2017-12-21'::timestamptz at time zone 'EST';
      timezone
---------------------
 2017-12-20 19:00:00
(1 row)

t=# select '2017-12-21'::timestamptz at time zone interval '-05:00';
      timezone
---------------------
 2017-12-20 19:00:00
(1 row)

但更进一步,文档说:

  

在文本案例中,可以通过任何方式指定时区名称   在第8.5.3节中描述。​​

https://www.postgresql.org/docs/current/static/datatype-datetime.html#DATATYPE-TIMEZONES

  

PostgreSQL允许您以三种不同的形式指定时区:

     
      
  • 已识别的时区名称列在pg_timezone_names
  • 中   
  • 认可的缩写列在pg_timezone_abbrevs
  • 中   
  • STDoffset或STDoffsetDST
  • 形式的POSIX样式时区规范   

(格式化我的)

最后:

  

应该警惕POSIX风格的时区功能可以导致   默默地接受虚假输入......要记住的另一个问题是   在POSIX时区名称中,正偏移用于 west 的位置   格林威治在其他任何地方,PostgreSQL都遵循ISO-8601   约定格林威治的正时区偏移 east

TL; DR

所以简而言之 - 当您将'-05'定义为timezone()函数或AT TIME ZONE指令的文本(非间隔)输入时(实际上相同)Postgres认为这是尝试使用POSIX样式时区从而反转符号,从而得到“相反”的结果......

这个记录的反演的简单演示:

t=# select '2017-12-21'::timestamptz at time zone '05';
      timezone
---------------------
 2017-12-20 19:00:00
(1 row)

答案 1 :(得分:1)

好的,我想我找到了自己问题的答案:

根据PostgreSQL文档,第9.9.3节中的以下链接https://www.postgresql.org/docs/9.6/static/functions-datetime.html

  

在这些表达式中,期望的时区区域可以指定为文本字符串(例如,“PST”)或间隔(例如,INTERVAL'-08:00')。在文本案例中,可以使用第8.5.3节中描述的任何方式指定时区名称。

因此,使用INTERVAL语法,以下似乎可行:

SELECT timezone(INTERVAL '-05:00', '2017-12-21');
      timezone       
---------------------
2017-12-20 19:00:00

我认为它仍然很奇怪,SELECT timezone('-05', '2017-12-21');究竟是什么意思,因为以下内容也提供了预期的结果(添加了TZ偏移量):

SELECT timezone('-05', '2017-12-21'::timestamp);
        timezone        
------------------------
2017-12-20 19:00:00+00