为什么/如何从PostgreSQL 8.4和9.2之间的“没有时区的时间戳”字段中提取(epoch …)的行为?

语境:

我们目前正在生产PostgreSQL 8.4,并在内部测试9.2以便将来升级.关于日期已经出现了一些问题.运行8.4和9.2的服务器在PostgreSQL版本和配置之外的各个方面都是相同的.相同的确切数据存储在两组服务器上;它是使用pg_dump和pg_restore传输的.

在我们数据库的一部分中,我们将日期存储在没有时区的时间戳类型的字段中.

问题:

从该字段访问日期时,提取(epoch ..)请求会返回截然不同的结果,具体取决于Postgres版本,如下所示:

#On Postgres 8.4. entered_timestamp is a "timestamp without time zone" type column:
SELECT entered_timestamp, extract(epoch from entered_timestamp) AS entered_timestamp from <table row>

 entered_timestamp      | entered_timestamp
 ----------------------------+-------------------
 2012-11-01 06:01:39.699612 |  1351774899.69961

但…

#On Postgres 9.2. All tables, schema, and data are identical, the SELECT statement is identical to the previous one:
SELECT entered_timestamp, extract(epoch from entered_timestamp) AS entered_timestamp from <table row>

 entered_timestamp      | entered_timestamp
 ----------------------------+-------------------
 2012-11-01 06:01:39.699612 |  1351749699.69961

如您所见,返回的时间戳是相同的,但返回的纪元号不是;事实上,他们已经过了几个小时.两台服务器上的服务器日期和Linux时区是相同的(彼此之间的秒数). Postgres时区也是相同的:在两台服务器上运行SELECT current_setting(‘timezone’)也会返回相同的数据.在两台服务器上运行SELECT now()会返回几乎相同的值.

题:

>提取(epoch …)在类型字段上的行为如何?
PostgreSQL 8.4和之间没有时区的时间戳改变了
PostgreSQL 9.2?
>为什么会发生这种变化?
>有没有办法在不改变我的架构的情况下阻止这种改变
或改变过去的数据(即基于配置的修复)?

最佳答案
在我自己的机器上测试,在PostgreSQL 8.4.10和9.2.1上得到1351749699.69961.

使用PostgreSQL 8.4.10,结果会根据会话时区而变化. 9.2,它没有.

可能这是这种变化的影响:Measure epoch of timestamp-without-time-zone from local not UTC midnight.被称为9.2兼容性变化.

更改说明中建议的解决方法是首先将时间戳转换为timestamptz:不仅仅是配置更改.

就个人而言,我发现9.2的行为更加舒适. Unix纪元被定义为UTC,因此这实际上意味着普通时间戳值被解释为UTC:这也是我使用它们的方式.

转载注明原文:为什么/如何从PostgreSQL 8.4和9.2之间的“没有时区的时间戳”字段中提取(epoch …)的行为? - 代码日志