postgresql – Postgres可以将时间戳与DST区分开来吗?

12月11日至4月4日,美国时钟从凌晨2点变为凌晨1点.例如,2AM CDT成为1AM CST.

这意味着在凌晨1点32分“发生了两次”:1:32 CDT(纪元1352010776642),1小时后1点32分CST(纪元1352014376642).

是否有可能以某种方式区分PostgreSQL中的普通时间戳类型?我们观察到的是,在CD的1:32,我们的应用程序存储日期为1352014376642(“第二次出现”).

最佳答案 据我所知,不是.

没有时区的TIMESTAMP(“普通时间戳”)就像您使用过的那样直接存储本地时间,同样没有存储相关的UTC偏移或时区.它是本地时间,所以除非您存储与当地时间相关的时区,否则它可以是许多不同时刻之一.

一旦转换为timestamptz并存储,就无法将“2012-01-01 11:00 0800”与“2012-01-01 11:00 0700”区分开来.因此,如果您有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)

如您所见,时区被忽略;它被剥离并丢弃.时间戳字段不是用于及时识别离散点的正确类型,因此您是SOL.

BTW,TIMESTAMP WITH TIME ZONE使用时区设置将时间戳转换为UTC以进行存储并返回到本地时区进行检索.它描述了一个瞬间(粗略地,见最后的链接).这意味着在timestamptz中,就像时间戳一样,原始时区丢失了.这很令人困惑,似乎与数据类型的名称相矛盾.显然,这就是标准的方式,所以无论它是否愚蠢,我们都会坚持下去.要区分时间戳,您还需要存储相关的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和TIME ZONE与转换前记录TZ偏移的内部UTC偏移相结合.

也就是说,you can’t rely on the clock not to double up timestamps or otherwise be bizarre,所以有必要让代码在时间上非常强大,并且不相信它有多大意义.

点赞