12月11日至4月4日,美国时钟从凌晨2点变为凌晨1点。例如,2AM CDT成为1AM CST。
这意味着上午1:32“发生了两次”:1:32 CDT(纪元1352010776642),1小时后1点32分CST(纪元1352014376642)。
是否有可能以某种方式区分PostgreSQL中的普通timestamp
类型的两个?我们观察到的是,在CD的1:32,我们的应用程序存储日期为1352014376642(“第二次出现”)。
答案 0 :(得分:2)
据我所知,没有。
TIMESTAMP WITHOUT TIME ZONE
(“普通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。
BTW,TIMESTAMP WITH TIME ZONE
使用timezone
设置将时间戳转换为UTC进行存储并返回本地时区进行检索。它描述了一个瞬间(粗略地,见最后的链接)。这意味着在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
与记录转换前TZ偏移量的内部UTC偏移量相结合。
那说,you can't rely on the clock not to double up timestamps or otherwise be bizarre无论如何,所以有必要让代码在时间上非常强大,并且不相信它有多大意义。