Postgres数据库中奇特的时区处理

时间:2016-11-24 23:13:05

标签: postgresql amazon-web-services timezone

我的环境

我在巴黎,法国UTC+1CET)。
它是12am00:00),我们在 2016年11月25日

我的 Postgres 数据库托管在eu-west-1区域的 Amazon Web Services (AWS RDS)上。

问题

查询具有特定时区设置的current_date(或current_time)似乎可以提供与......我的信念不一致的结果。

特别是,在使用current_date时区或CET时,查询UTC+1会产生不同的结果。

实施例

SET TIME ZONE 'UTC+01';
select current_date, current_time;
+------------+--------------------+
| date       | timetz             |
+------------+--------------------+
| 2016-11-24 | 22:00:01.581552-01 |
+---------------------------------+

不,那是昨天 - 两个小时前。

SET TIME ZONE 'CET';
select current_date, current_time;

SET TIME ZONE 'Europe/Paris';
select current_date, current_time;
+------------+--------------------+
| date       | timetz             |
+------------+--------------------+
| 2016-11-25 | 00:00:01.581552-01 |
+---------------------------------+

有正确的时间和日期。

问题

那里发生了什么? 对我来说为时已晚,我混淆了UTC+1UTC-1还是有更大的东西让我俯视? AWS RDS是否在此中发挥作用?

1 个答案:

答案 0 :(得分:2)

这个问题似乎与Amazon RDS无关:它与PostgreSQL使用的约定有关。在这种情况下,您执行后退时区名称。你的意思是 'UTC-01' ,你写的是 'UTC+01'
来自the manual

  

要记住的另一个问题是在POSIX时区名称中,   正偏移用于格林威治的 west 位置。到处   否则,PostgreSQL遵循ISO-8601惯例,即积极的   时区偏移是格林威治的

因此,用于SET TIME ZONE的时区字符串(以及相应的SHOW timezone的显示)或AT TIME ZONE构造使用相反符号显示的内容timestampwith time zone)文字!这是ISO和SQL标准与POSIX之间非常不幸的分歧。 (我认为POSIX应该受到指责。)见:

但巴黎的 'CET''UTC-01'仍可能存在错误,因为他们没有考虑夏令时的规则。<登记/> (DST是人类历史上最愚蠢的概念之一。)

巴黎(与欧洲大部分地区一样)在冬季使用CET,在夏季使用CEST。您'CET'的测试恰好在11月开始工作。如果您在夏天尝试相同的操作,则会得到错误的结果。

为安全起见,请始终使用考虑DST规则的时区名称 'Europe/Paris'。电话费用更高。

如果您的时区设置意味着任何,则函数current_time会将DST规则考虑在内。但'UTC-01'是一个明确的时间偏移。我从不使用数据类型time with time zonecurrent_time开头。手册再次出现:

  

我们建议使用time with time zone类型(虽然它是   PostgreSQL支持遗留应用程序和合规性   使用SQL标准)

考虑:

SELECT '2016-06-06 00:00+0'::timestamptz AT TIME ZONE 'UTC+01' AS plus_wrong
     , '2016-06-06 00:00+0'::timestamptz AT TIME ZONE 'UTC-01' AS minus_right
     plus_wrong      |     minus_right     
---------------------+---------------------
 2016-06-05 23:00:00 | 2016-06-06 01:00:00
SELECT '2016-01-01 00:00+0'::timestamptz AT TIME ZONE 'CET'    AS cet_winter
     , '2016-06-06 00:00+0'::timestamptz AT TIME ZONE 'CEST'   AS cest_summer
     , '2016-06-06 00:00+0'::timestamptz AT TIME ZONE 'CET'    AS cet_no_dst  -- CET wrong!
     cet_winter      |     cest_summer     |     cet_no_dst      
---------------------+---------------------+---------------------
 2016-01-01 01:00:00 | 2016-06-06 02:00:00 | 2016-06-06 01:00:00  -- wrong
SELECT '2016-06-06 00:00+0'::timestamptz AT TIME ZONE 'Europe/Paris' AS paris_summer
     , '2016-01-01 00:00+0'::timestamptz AT TIME ZONE 'Europe/Paris' AS paris_winter
 paris_summer         | paris_winter
----------------------+----------------------
 2016-06-06 02:00:00  | 2016-01-01 01:00:00  -- always right

相关: