Postgres 数据库中的特殊时区处理
问题:Postgres 数据库中的特殊时区处理
我的环境
我在法国巴黎(UTC+1或CET)。
它是12am(00:00),我们在 2016 年 11 月 25 日。
我的 Postgres 数据库托管在eu-west-1区域的 Amazon Web Services (AWS RDS) 上。
问题
查询具有特定时区集的current_date(或current_time)似乎提供的结果与......我的信念不一致。
特别是,当使用CET时区或UTC+1时区时,查询current_date会产生不同的结果。
示例
SET TIME ZONE 'UTC+01';
select current_date, current_time;
+------------+--------+
| 日期 |时间 |
+------------+--------+
| 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;
+------------+--------+
| 日期 |时间 |
+------------+--------+
| 2016-11-25 | 00:00:01.581552-01 |
+----------------------------------+
有正确的时间和日期。
问题
那里发生了什么事?
对我来说太晚了,我混淆了UTC+1和UTC-1还是有一些更大的东西我忽略了? AWS RDS 是否在其中发挥作用?
解答
这个问题似乎与 Amazon RDS 无关:它与 PostgreSQL 使用的约定有关。在这种情况下,您_do_ 有_time zone name_ 向后。你的意思是 'UTC-01' 你写'UTC+01'的地方。
从手册:
要记住的另一个问题是,在 POSIX 时区名称中,正偏移用于格林威治西部的位置。在其他任何地方,PostgreSQL 都遵循 ISO-8601 约定,即正时区偏移量是格林威治的东。
因此,用于SET TIME ZONE(以及相应地显示SHOW timezone)或AT TIME ZONE构造的时区字符串使用timestamp(with time zone) 文字中显示的相反符号!一方面,这是 ISO 和 SQL 标准与另一方面 POSIX 之间非常不幸的分歧。 (我认为 POSIX 是罪魁祸首。)见:
-
带有 AT TIME ZONE 和 UTC 偏移量的奇数
-
为什么 PostgreSQL 将数字 UTC 偏移解释为 POSIX 而不是 ISO-8601?
但是对于巴黎来说,'CET'或'UTC-01'仍然可能是错误的,因为它们没有考虑到夏令时的规则。
(夏令时是人类历史上最愚蠢的概念之一。)
巴黎(与欧洲大部分地区一样)在冬季使用 CET,在夏季使用 CEST。您对'CET'的测试恰好在 11 月进行。如果你在夏天尝试同样的方法,你会得到错误的结果。
为了安全起见,请始终使用考虑 DST 规则的时区名称'Europe/Paris'。通话更贵。
如果您的时区设置暗示任何时区设置,函数current_time会考虑 DST 规则。但是'UTC-01'是一个普通的时间偏移量。我从不使用数据类型time with time zone或current_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
加错 |减右
---------------------+---------------------
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 -- 错误
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
巴黎夏季 |巴黎冬季
----------------------+----------
2016-06-06 02:00:00 | 2016-01-01 01:00:00 -- 永远正确
zoz100069`
有关的:
-
在 Rails 和 PostgreSQL 中完全忽略时区
-
具有相同属性的时区名称在应用于时间戳时会产生不同的结果
-
数据类型“带时区的时间戳”的时区存储
更多推荐
所有评论(0)