我在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
具有相同的偏移...有什么想法吗?感谢。
答案 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小时。
-05
和EST
都为SET TIMEZONE
提供了相同的结果,如文档中所述。
现在,您使用interval
:https://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 。
所以简而言之 - 当您将'-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