为什么 Postgres 中的时区在 0001 年与 UTC 有如此疯狂的偏移?

Bas*_*que 16 postgresql timestamp timezone postgresql-9.5

在 Postgres 9.5 中,我很惊讶地看到在尝试 year 0001(没有 year zero 0000)时看到的结果。

的偏移量-07:52:58

一些示例代码。请注意,我混合使用了TIMESTAMP WITH TIME ZONETIMESTAMP WITHOUT TIME ZONE,所以请仔细阅读。

SET TIME ZONE 'America/Los_Angeles' ;

SELECT (TIMESTAMP WITH TIME ZONE '2015-01-01 00:00:00.0', 
        TIMESTAMP WITH TIME ZONE '0001-01-01 00:00:00.0Z', 
        TIMESTAMP WITHOUT TIME ZONE '0001-01-01 00:00:00.0Z') ;

("2015-01-01 00:00:00-08","0001-12-31 16:07:02-07:52:58 BC","0001-01-01 00:00:00")
Run Code Online (Sandbox Code Playgroud)

我对第二个值感到惊讶:0001-12-31 16:07:02-07:52:58 BC. 我知道我们必须America/Los_Angeles在 UTC后八小时后退八小时,偏移量为-08:00. 但不是-08:00偏移量是-07:52:58. 为什么?

UTC下没问题

在 UTC 下输入数据时没有这样的问题。

SET TIME ZONE 'UTC' ;

SELECT (TIMESTAMP WITH TIME ZONE '2015-01-01 00:00:00.0',  
        TIMESTAMP WITH TIME ZONE '0001-01-01 00:00:00.0Z', 
        TIMESTAMP WITHOUT TIME ZONE '0001-01-01 00:00:00.0Z');

("2015-01-01 00:00:00+00","0001-01-01 00:00:00+00","0001-01-01 00:00:00")
Run Code Online (Sandbox Code Playgroud)

没有零年

顺便说一句,日期部分似乎是正确的。似乎没有年份0000,那是“BC”和“AD”时代之间的支点。取 0001 年的第一个时刻,减去一个小时,你就得到了年份0001 BC——所以没有年份零。

SET TIME ZONE 'UTC' ;

INSERT INTO moment_  -- TIMESTAMP WITH TIME ZONE.
VALUES ( TIMESTAMP '0001-01-01 00:00:00.0Z' - INTERVAL '1 hour' ) ;

SET TIME ZONE 'UTC' ;

TABLE moment_ ;
Run Code Online (Sandbox Code Playgroud)

结果是年份0001 BC,所以我们从0001to跳转0001 BC;没有零年0000

"0001-12-31 23:00:00+00 BC"
Run Code Online (Sandbox Code Playgroud)

jca*_*ron 22

1883 年 11 月 18 日 12:00(新时间),美国铁路采用标准时间。

这意味着在那之前,洛杉矶使用基于平均太阳时的实际当地时间。之后,它被移至当地时区,该时区与格林威治标准时间有几个小时的整体偏移,与之前的时间略有不同。

想知道更多?

  • IANA下载 tzdata 时区数据库:时区

  • 在里面,你会发现(许多)时区的定义,随着时间的推移有很多变化,还有很多评论详细说明了什么地方和时间发生了什么变化。读起来很有趣!

  • 维基百科也有一些有趣的事实,在维基百科:时区页面,关于 1883 年,11 月 18 日的变化:

铁路时间
……
19 世纪中叶美国铁路上的计时有些混乱。每条铁路使用自己的标准时间,通常基于其总部或最重要终点站的当地时间,并且铁路的列车时刻表使用自己的时间发布。由几条铁路服务的一些路口为每条铁路都有一个时钟,每个时钟显示不同的时间。
... Dowd 的系统从未被美国铁路公司接受。相反,美国和加拿大的铁路实施了由 Traveler's Official Railway Guide 的编辑 William F. Allen 提出的版本。其时区的边界穿过火车站,通常位于主要城市。例如,东部和中部时区之间的边界穿过底特律、布法罗、匹兹堡、亚特兰大和查尔斯顿。它于1883 年 11 月 18日星期日落成,也被称为“两个中午的日子”,当时每个火车站的时钟都被重置,因为每个时区都达到了标准时间中午。这些区域被命名为 Intercolonial、Eastern、Central、Mountain 和 Pacific。...

另请注意,这并非特定于 Postgresql。这对于使用 tzdata 数据库的任何软件或操作系统都有效(当然,许多将被限制在 1970 年或 1901 年之后的日期,因此 1883 年是无法实现的,但是还有很多很多其他的调整在不同的时间)。