具有 AT TIME ZONE 和 UTC 偏移量的奇数

Asa*_*vid 7 postgresql timestamp utc-time timezone

我不明白这两列之间的区别。美国/芝加哥时区是 UTC-6,所以我希望两者都返回相同的结果:

select timezone('America/Chicago', '2017-01-01 12:00:00'::TIMESTAMP AT TIME ZONE 'UTC'),
       timezone('UTC-6'          , '2017-01-01 12:00:00'::TIMESTAMP AT TIME ZONE 'UTC');
Run Code Online (Sandbox Code Playgroud)

然而,结果是:

2017-01-01 06:00:00 | 2017-01-01 18:00:00
Run Code Online (Sandbox Code Playgroud)

而且,这种行为非常尴尬,

SELECT '1:00 -1'::time with time zone AT TIME ZONE '-1'; 
  timezone   
-------------
 03:00:00+01
Run Code Online (Sandbox Code Playgroud)

谁能解释一下?

Erw*_*ter 12

时区名称缩写或简单的时区偏移量包含更多信息。'UTC-6'是一种“POSIX 风格的时区规范”,它只是一个缩写加上偏移量。时区
手册:

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

  • 完整的时区名称,例如America/New_York。[...]

  • 时区缩写,例如PST。[...]

  • 除了时区名称和缩写,PostgreSQL 将接受形式为STDoffsetor 的 POSIX 风格的时区规范STDoffsetDST,其中STD是区域缩写,偏移量是 offsetUTC 以西的小时数,并且DST是可选的夏令时区缩写,假设在给定的偏移量前一小时站立。

你观察到的差异源于另一个奇怪的地方。你必须使用+而不是-

timezone('UTC+6', '2017-01-01 12:00:00'::TIMESTAMP AT TIME ZONE 'UTC')
Run Code Online (Sandbox Code Playgroud)

又是说明书:

要记住的另一个问题是,在 POSIX 时区名称中,格林威治以西的位置使用正偏移量。在其他任何地方,PostgreSQL 都遵循 ISO-8601 约定,即正时区偏移位于格林威治以东

然而,即使修正了偏移错误,两个表达式仍然不等价。除此之外,像“美国/芝加哥”这样的时区名称也会考虑夏令时 (DST) 的规则。

顺便说一句,您的表达式可以简化为:

timestamptz '2017-01-01 12:00:00 +0' AT TIME ZONE 'UTC+6'
Run Code Online (Sandbox Code Playgroud)

但您可能希望时区名称是安全的:

timestamptz '2017-01-01 12:00:00 +0' AT TIME ZONE 'America/Chicago'
Run Code Online (Sandbox Code Playgroud)

有关的:


要解决您的第二个示例

SELECT '1:00 -1'::time with time zone AT TIME ZONE '-1';
Run Code Online (Sandbox Code Playgroud)

简化的等效语法:

SELECT timetz '1:00 -1' AT TIME ZONE '-1';
Run Code Online (Sandbox Code Playgroud)

文字的两个实例-1具有不同的含义。第一个偏移量是*timetz*表示格林威治以东位置的文字的一部分(符合 SQL 标准)。第二个是POSIX 风格的时区规范,表示格林威治以西的偏移量。在没有区域规范的情况下,UTC 被假定为基准。看:

还要注意的是,AT TIME ZONE构建回报timetztimetz投入。它只是根据不同的偏移量重新设置时间文字。这与它与timestamp/ timestamptzinput 的使用不同,其中数据类型也被切换。

但不使用的数据类型timetztime with time zone在所有。它被设计破坏了,只包含在 Postgres 中,因为它是标准 SQL 的一部分。明确不鼓励使用它。看:

  • 这是一个超级有用的答案。 (2认同)