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
]
(像前面一样,在实际使用中不应该包含空格.)
在夏令时开始时定义dstdate
和 dsttime
字段,
在标准时间开始时定义stddate
和 stdtime
定义。
(在某些情况下,特别是在赤道以南地区,前者可能比后者在一年内更晚。) 日期字段具有如下格式之一:
n
普通整数表示一年中的哪一天,从0到364,或者在闰年到365。
J
n
在这种格式下,n
计数从1到365,即使2月29日存在,也不被计算。
(因此,不能以这种方式指定发生在2月29日的转换。然而,无论是否是闰年,2月之后的天数都是相同的,所以对于固定日期的转换,这种形式通常比纯整数形式更有用。)
M
m
.
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 点结束。
四个时区名称 EST5EDT
,CST6CDT
、MST7MDT
和PST8PDT
看起来像是POSIX区域规范。
但是,它们实际上被用来命名时区,因为(出于历史原因)IANA 时区数据库中存在这些名称的文件。
这样做的实际含义是,这些区域名称将产生有效的历史上的美国夏令时转换,即使普通POSIX规范不会产生。
需要警惕的是很容易拼错 POSIX 样式的时区规范,因为没有检查区域缩写的合理性。
例如,SET TIMEZONE TO FOOBAR0
将工作,让系统有效地使用UTC的一个相当奇特的缩写。