postgresql - Postgres 可以区分时间戳和夏令时吗?

标签 postgresql timezone dst

2012 年 11 月 4 日,美国冬令时从凌晨 2 点调整到凌晨 1 点。例如,CDT 凌晨 2 点变成了 CST 凌晨 1 点。

这意味着在凌晨 1:32“发生了两次”:CDT 1:32(纪元 1352010776642)和一个小时后的 CST 1:32(纪元 1352014376642)。

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

最佳答案

据我所知,没有。

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 使用 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无论如何,因此有必要拥有对时间非常稳健并且不相信它有多大意义的代码。

关于postgresql - Postgres 可以区分时间戳和夏令时吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13231557/

相关文章:

postgresql - UPSERT Postgres 9.5

database - 流复制和逻辑复制的区别

javascript - 将特定日期转换为 悉尼 时区

Java TimeZoneUpdater 因 java.io.EOFException 崩溃

ruby-on-rails - 菲律宾马尼拉使用什么时区

c++ - 在 Windows XP/Server 2003 下将新旧本地时间转换为 UTC

postgresql - 如何在 PostgreSQL 中计算年龄(datfrozenxid)?

sql - 如何高效存储百万条统计记录?

c++ - 守护进程中的 DST 更改处理 (*NIX)

java - 将 UTC 时间戳插入 MySQL - 夏令时时区