阅读(388) (15)

PostgreSQL POSIX 时区规范

2021-08-24 15:07:42 更新

PostgreSQL可以接受根据POSIX标准的针对TZ环境变量的规则编写的时区规范。 POSIX时区规范不足以处理真实世界时区历史的复杂性,但有时使用它们是有原因的。

POSIX时区规范具有形式

STD offset [ DST [ dstoffset ] [ , rule ] ]

(为了可读性,我们在字段之间显示空格,但在实践中不应使用空格.) 这些区域包括:

  • STD 是用于标准时间的区域缩写。

  • offset 是区域相对UTC的标准时间偏移量。

  • DST是用于夏令时的区域缩写。如果省略此字段和以下字段,则该区域使用没有夏令时规则的固定 UTC 偏移量。

  • dstoffset是相对UTC 的夏令时偏移。 此字段通常会被省略,因为它默认会比标准时间offset少一个小时,这通常是正确的。

  • rule定义夏令时生效的规则,如下所述。

在此语法中,区域缩写可以是字母字符串,如 EST,或者是被尖括号包围的任意字符串,如 <UTC-05>。 请注意,此处给出的区域缩写仅用于输出,即使这样也仅用于某些时间戳输出格式。 时间戳输入中识别的区域缩写按照第 B.4 节解释的那样来确定。

偏移字段指定为小时(可选为分钟和秒),与 UTC 的差异。 它们包括格式hh[:mm[:ss]] 可选带有前导符号 (+-). 正符号用于格林威治west区域。(请注意,这与在PostgreSQL中其他地方使用的ISO-8601符号约定相反。) hh可以有1或2位数字; mm ss (如果使用)必须包含两位数字。

夏令时转换rule的格式为

dstdate [ / dsttime ] , stddate [ / stdtime ]

(像前面一样,在实际使用中不应该包含空格.) 在夏令时开始时定义dstdatedsttime 字段, 在标准时间开始时定义stddatestdtime 定义。 (在某些情况下,特别是在赤道以南地区,前者可能比后者在一年内更晚。) 日期字段具有如下格式之一:

n

普通整数表示一年中的哪一天,从0到364,或者在闰年到365。

Jn

在这种格式下,n计数从1到365,即使2月29日存在,也不被计算。 (因此,不能以这种方式指定发生在2月29日的转换。然而,无论是否是闰年,2月之后的天数都是相同的,所以对于固定日期的转换,这种形式通常比纯整数形式更有用。)

Mm.n.d

此格式指定始终在同一月和一周的同一天发生的转换。 m表示月,从1到12。 n指定第n个按d标识的星期日期(weekday)。 n为 1 和 4 之间的数字,或 5 表示该月中此星期日期(weekday)的最后一次出现(可能是第四或第五个)。 d为 0 和 6 之间的数字,0 表示星期日。 例如,M3.2.0意味着3月的第二个星期日

注意

M格式足以描述许多常见的夏令时转换定律。 但请注意,这些变体都无法处理夏令时法律的更改,因此在实践中,为命名时区(IANA 时区数据库中)存储的历史数据对于正确解释过去的时间戳是必要的。

转换规则中的时间字段的格式与前面描述的偏移字段相同,除了它们不能包含符号。 它们定义对另一个时间发生更改的当前本地时间。如果省略,则默认为 02:00:00

如果给定了夏令时缩写,但省略了转换rule字段, 回退的行为是使用规则 M3.2.0,M11.1.0,这对应于美国截至 2020 年的做法。 (也就是说, 春天在3 月的第二个星期日向前,秋天在11 月的第一个星期日向后, 两个转换都发生在凌晨 2 点)。 请注意,此规则没有给出 2007 年之前的正确的美国转换日期。

例如,CET-1CEST,M3.5.0,M10.5.0/3描述了巴黎的当前(截至2020年)的计时做法。 该规范说明标准时间缩写为 CET,并且比 UTC 的早(东)一小时; 夏令时缩写为CEST,并且隐式比 UTC 早两个小时; 夏令时从 CET 3 月的最后一个星期日开始,到CEST 10 月的最后一个星期日凌晨 3 点结束。

四个时区名称 EST5EDTCST6CDTMST7MDTPST8PDT看起来像是POSIX区域规范。 但是,它们实际上被用来命名时区,因为(出于历史原因)IANA 时区数据库中存在这些名称的文件。 这样做的实际含义是,这些区域名称将产生有效的历史上的美国夏令时转换,即使普通POSIX规范不会产生。

需要警惕的是很容易拼错 POSIX 样式的时区规范,因为没有检查区域缩写的合理性。 例如,SET TIMEZONE TO FOOBAR0将工作,让系统有效地使用UTC的一个相当奇特的缩写。