据我所知,没有。
TIMESTAMP WITHOUT TIME ZONE
(“plain” timestamp
)就像您使用的那样直接存储本地时间,同样不存储关联的 UTC 偏移量或时区。它是本地时间,因此除非您存储与该本地时间关联的时区,否则它可能是许多不同的时间之一瞬间。
没有办法区分'2012-01-01 11:00 +0800'
一次'2012-01-01 11:00 +0700'
转换为timestamptz
和存储。因此,如果您有一个 DST 班次导致一个小时在不同的时区重播,您将无法重建该信息。见证:
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
字段不是用于识别离散时间点的正确类型,因此您是 SOL。
顺便说一句,TIMESTAMP WITH TIME ZONE
使用设置将时间戳转换为 UTC 进行存储并返回本地时区进行检索timezone
。它描述了一个瞬间(大致,见最后的链接)。这意味着在timestamptz
,timestamp
原来的时区一样丢失了。这令人困惑,并且似乎与数据类型的名称相矛盾。显然,标准就是这样,所以无论它是否愚蠢,我们都坚持使用它。为了区分时间戳,您还需要存储相关的 UTC 偏移量。最好命名为TIMESTAMP WITH TIME ZONE CONVERSION
.
这timestamptz
对于存储离散的时间点很有好处,但对于存储在现实世界当地时间何时发生的事件并没有多大好处。同时存储 UTC 偏移量和/或 tzname。
看:
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
与内部 UTC 偏移量结合,记录转换前的 TZ 偏移量。
也就是说,你不能依靠时钟来不加倍时间戳或以其他方式变得奇怪,因此有必要拥有对时间非常健壮并且不相信它有多大意义的代码。