PostgreSQL 可以接受根据POSIXTZ
环境变量的标准规则编写的时区规范。POSIX时区规范不足以应对现实世界时区历史的复杂性,但是有时有理由使用它们。
POSIX 时区规范的格式为
STD
offset
[DST
[dstoffset
] [ ,rule
] ]
(为了可读性,我们在字段之间显示空格,但实际上不应该使用空格。)字段为
STD
是用于标准时间的分区缩写。
offset
是分区从 UTC 的标准时差。
DST
是用于夏令时的分区缩写。如果省略此字段及以下字段,则分区使用具有固定 UTC 时差且没有夏令时规则。
dstoffset
是与世界协调时间有关的夏令时偏移。通常会省略此字段,因为它默认为比标准时间 offset
少一小时,这通常是正确的时间设置。
rule
定义了夏令时生效规则,如下所述。
在此语法中,时区缩写可以是字母串,如 EST
,也可以是包含在尖括号中的任意字符串,如 <UTC-05>
。请注意,此处提供的时区缩写仅用于输出,并且即使用于输出也只用于某些时间戳输出格式。时间戳输入中识别的时区缩写由 B.4 节 中的解释确定。
偏移量字段指定小时数,以及(可选)与世界协调时间的分钟数和秒数之差。它们具有以下格式:hh
[:
mm
[:
ss
]],还可以选择使用前置符号(+
或 -
)。正号用于格林威治“西”部的时区。(请注意,这与 PostgreSQL 中其他地方使用的 ISO-8601 符号约定相反。)hh
可以包含一个或两个数字;如果使用 mm
和 ss
,它们必须包含两个数字。
夏令时转换 rule
的格式为
dstdate
[/
dsttime
],
stddate
[/
stdtime
]
(如前所述,在实际应用中不应包含空格。)dstdate
和 dsttime
字段定义夏令时开始时间,而 stddate
和 stdtime
定义标准时间开始时间。(在某些情况下,特别是赤道以南的时区,前者可能比后者在一年中晚些时候出现。)日期字段具有以下格式之一
n
一个普通整数表示一年中的某一天,从 0 计数到 364,或在闰年中计数到 365。
J
n
在此形式中,n
从 1 计数到 365,即使存在 2 月 29 日也不会将其计数在内。(因此,无法通过此方式指定 2 月 29 日发生的转换。然而,无论是不是闰年,闰日后的日子都是相同的数字,因此此形式通常比普通整数形式更适用于固定日期上的转换。)
M
m
.
n
.
d
此表单说明了总是在同一个月和同一周天的同一时期发生的转型。m
标识月份,范围是 1 至 12。n
指定d
标识的工作日的第n
次出现。n
是 1 和 4 之间的一个数字,或 5 表示该工作日在这个月出现的最后一次(可能是第四次或第五次)。d
是 0 和 6 之间的一个数字,其中 0 表示周日。例如,M3.2.0
表示“三月的第二个星期日”。
M
格式足以描述许多常见的夏令时转换规律。但请注意,这些变体均无法处理夏令时法律更改,因此在实际操作中,存储在已命名时区的历史数据(在 IANA 时区数据库中)对于正确解释过去的时间戳是必要的。
转换规则中的时间字段格式与之前描述的偏移字段相同,不同之处在于它们不包含符号。它们定义了更改为另一个时间时发生的当前当地时间。如果省略,它们将默认为02:00:00
。
如果给出了夏令时缩写但省略了转换rule
字段,则后备行为是使用规则M3.2.0,M11.1.0
,该规则对应于 2020 年的美国做法(即,在三月的第二个星期日向前推进,在十一月的第一个星期日回退,两次转换均发生在当前时间的凌晨 2 点)。请注意,此规则不会提供 2007 年之前年份的正确美国转换日期。
例如,CET-1CEST,M3.5.0,M10.5.0/3
描述了巴黎目前(截至 2020 年)的计时做法。此规范表示标准时间的缩写为CET
,比 UTC 早一小时(东部);夏令时的缩写为CEST
,隐式地比 UTC 早两个小时;夏令时从三月的最后一周日的凌晨 2 点(CET 时间)开始,在十月的最后一个星期日的凌晨 3 点(CEST 时间)结束。
这四个时区名称EST5EDT
、CST6CDT
、MST7MDT
和PST8PDT
看起来像是 POSIX 区域规范。但是,它们实际被视为已命名的时区,因为(出于历史原因)IANA 时区数据库中存在使用这些名称的文件。这样做的实际含义是,即使一般的 POSIX 规范不适用,这些区域名称也会产生有效的美国历史夏令时过渡。
需要注意的是,POSIX 样式时区规范很容易拼写错误,因为对于时区缩写没有合理性的检查。例如,SET TIMEZONE TO FOOBAR0
将起作用,让系统有效地针对 UTC 使用一种相当奇怪的缩写。