据我所知,不是这样的。
像您使用的“不带时区的时间戳”(“plain timestamp”)一样,直接存储本地时间,而不存储关联的UTC偏移量或时区。它是本地时间,因此,除非您存储了与该本地时间相关联的时区,否则它可能是许多不同瞬间中的一个。
一旦转换为“带时区的时间戳”(“timestamptz”)并存储,就无法区分“2012-01-01 11:00 +0800”和“2012-01-01 11:00 +0700”。因此,如果夏令时转移导致在不同的时区重播一个小时,您将无法重构该信息。请看:
regress=> select extract(epoch from '2012-01-01 11:00 +0800'::timestamp),
extract(epoch from '2012-01-01 11:00 +700'::timestamp);
date_part | date_part
1325415600 | 1325415600
(1 row)
正如您所看到的,时区被忽略了;它被剥离并丢弃了。时间戳字段不是用于识别时间点的正确类型,因此您无法解决这个问题。
顺便提一下,
TIMESTAMP WITH TIME ZONE
会将时间戳转换为协调世界时(UTC)进行存储,并使用
timezone
设置将其转换回本地时区进行检索。它描述了一个瞬间(大致如此,请参见末尾的链接)。这意味着在
timestamptz
中,就像在
timestamp
中一样,
原始时区已经丢失。这很令人困惑,似乎与数据类型的名称相矛盾。显然,这就是标准规定,所以无论是否愚蠢,我们都必须遵守它。要区分时间戳,您还需要存储相关的UTC偏移量。最好将其命名为
TIMESTAMP WITH TIME ZONE CONVERSION
。
这使得
timestamptz
非常适合存储时间点,但不适合存储事件发生的实际本地时间。请同时存储UTC偏移量和/或时区名称。
请参阅:
regress=> select extract(epoch from '2012-01-01 01:00 CST'::timestamptz),
extract(epoch from '2012-01-01 02:00 CDT'::timestamptz);
date_part | date_part
1325401200 | 1325401200
遗憾的是,没有一种数据类型将
TIMESTAMP WITH TIME ZONE
与记录转换前的TZ偏移量的内部UTC偏移量结合起来。
话虽如此,
您不能依赖时钟不会重复时间戳或以其他方式变得奇怪,因此有必要编写非常强大的关于时间的代码,并且不信任它会有多大意义。