Postgres数据库中奇特的时区处理
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Postgres数据库中奇特的时区处理相关的知识,希望对你有一定的参考价值。
我的环境
我在法国巴黎(UTC+1
或CET
)。
这是12am
(00: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+1
和UTC-1
,还是有更大的东西让我忽略? AWS RDS是否在此中发挥作用?
这个问题似乎与Amazon RDS无关:它与PostgreSQL使用的约定有关。在这种情况下,您确实有向后的时区名称。你的意思是你写的'UTC-01'
'UTC+01'
。
来自the manual:
另外要记住的一个问题是,在POSIX时区名称中,正偏移用于格林威治以西的位置。在其他地方,PostgreSQL遵循ISO-8601惯例,正面时区偏移位于格林威治以东。
因此,用于SET TIME ZONE
的时区字符串(以及相应的SHOW timezone
的显示)或AT TIME ZONE
构造使用与timestamp
(with time zone
)文字中显示的相反的符号!这是ISO和SQL标准与POSIX之间非常不幸的分歧。 (我认为POSIX应该受到指责。)参见:
- Oddities with AT TIME ZONE and UTC offsets
- Why does PostgreSQL interpret numeric UTC offset as POSIX and not 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
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
有关:
- Ignoring time zones altogether in Rails and PostgreSQL
- Time zone names with identical properties yield different result when applied to timestamp
- Time zone storage in data type "timestamp with time zone"
以上是关于Postgres数据库中奇特的时区处理的主要内容,如果未能解决你的问题,请参考以下文章
时区感知 postgres 查询为分钟、小时、天创建时间序列
使用 node-postgres 在 utc 中获取 Postgres“没有时区的时间戳”