【问题标题】:Peculiar time zone handling in a Postgres databasePostgres 数据库中的特殊时区处理
【发布时间】:2017-04-09 07:16:37
【问题描述】:

我的环境

我在法国巴黎UTC+1CET)。
我是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+1UTC-1 搞混了还是有什么更大的东西我忽略了? AWS RDS 是否在其中发挥作用?

【问题讨论】:

    标签: postgresql amazon-web-services timezone


    【解决方案1】:

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

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

    因此,用于SET TIME ZONE(以及相应地显示SHOW timezone)或AT TIME ZONE 构造的时区字符串使用timestamp (@987654333) 中显示的相反符号 @) 文字!一方面,这是 ISO 和 SQL 标准与另一方面 POSIX 之间非常不幸的分歧。 (我认为 POSIX 是罪魁祸首。)请参阅:

    但是 'CET''UTC-01' 对于巴黎来说仍然可能是错误的,因为他们没有考虑到夏令时的规则。
    (夏令时是人类历史上最愚蠢的概念之一。)

    巴黎(与欧洲大部分地区一样)在冬季使用 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
    

    相关:

    【讨论】:

    • 见鬼,我想我一定是弄错了,但我不知道有一个约定,正时区偏移不对应于正实际时间抵消。好吧,正如您所指出的,我们已经看到并用时间表示做了更糟糕的事情!感谢您对手册的超级清晰参考以及非常有用的额外信息,这些信息将防止我在几个月内摸不着头脑:)
    猜你喜欢
    • 2010-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-05
    • 1970-01-01
    • 2018-05-13
    • 1970-01-01
    相关资源
    最近更新 更多