【问题标题】:Why do Postgres timezones change around 1967/68?为什么 Postgres 时区会在 1967/68 年左右发生变化?
【发布时间】:2014-05-12 18:43:08
【问题描述】:

在 9.3.3 上,如果运行:

select EXTRACT(TIMEZONE FROM timestamp with time zone '1911-03-01 00:00 -8:00:00'), EXTRACT(TIMEZONE FROM timestamp with time zone '1911-05-15 00:00 -8:00:00'), EXTRACT(TIMEZONE FROM timestamp with time zone '1917-03-01 00:00 -8:00:00'), EXTRACT(TIMEZONE FROM timestamp with time zone '1917-05-15 00:00 -8:00:00'), EXTRACT(TIMEZONE FROM timestamp with time zone '1967-03-01 00:00 -8:00:00'), EXTRACT(TIMEZONE FROM timestamp with time zone '1967-05-15 00:00 -8:00:00'), EXTRACT(TIMEZONE FROM timestamp with time zone '1968-03-01 00:00 -8:00:00'), EXTRACT(TIMEZONE FROM timestamp with time zone '1968-05-15 00:00 -8:00:00');

得到以下结果:

0;0;
0;3600;
0;3600;
3600;3600

(第一次是拉斯维加斯的创始日,后面几个是我用来调试的问题)

似乎在 1911 年左右没有偏移量,1911 年和 1967 年之间的偏移量在夏季而不是冬季,然后从 1968 年开始总是有一个。这似乎有点奇怪。有谁知道这里的偏移量是怎么回事,这是否是预期的行为,或者我的 linux 设置中是否有一些我可能会改变的东西?

【问题讨论】:

  • 你的时区是哪个?
  • 我在伦敦,刚刚进入夏令时(因此我调查了时区!)。
  • 我不是在问你的“真实”时区,而是你在 postgresql 中配置的时区(这会影响结果)。运行`显示时区;`
  • "-8:00:00" 不是时区!这只是一个偏移量。

标签: postgresql timezone timestamp-with-timezone


【解决方案1】:

您所在时区的规则是由法律规定的,并且法律会发生变化。

【讨论】:

  • 这些定律是否在某处列举,所以我可以确定它为什么会这样?
  • 所以这里是 zoneinfo 数据库的公共存储库,采用人类可读格式:github.com/eggert/tz/blob/master/northamerica。寻找处理太平洋时间的洛杉矶,没有提到为什么事情会在 1911 年和 1921 年之间发生变化(看看 400 行)。
  • @WilliamBecker,您使用的是“GB”时间,而不是太平洋时间。如果你想告诉 PostgreSQL 就像你在不同的区域一样,你必须告诉它这样做。
  • 我没有。当我给它一个明确的偏移量时,我只是很困惑我的本地时区如何影响timestamp with time zone 中保存的数据。我认为偏移量是相对于 UTC 的,而不是我的当地时间。这是ISO8601 offset,所以应该来自UTC,对吧?
  • 您在问“在这个给定的时刻,UTC 和我当前时区之间的偏移量是多少”。您使用偏移量拼写了瞬间,但这不是您询问 postgres 的偏移量。无论你如何拼写它,postgres 都会将其折叠为规范值。
【解决方案2】:

如果您想存储拉斯维加斯的(本地)时钟在城市成立之日标记为 00:00:00 的 INSTANT,并假设拉斯维加斯使用的偏移量为 -8 小时,那么您应该将1911-03-01 00:00 -8:00:00::timezonetx 存储在timezonetx 字段中。但是请注意,真正存储的只是“通用瞬间”,当您阅读它时,您无法知道它对应于哪个“拉斯维加斯当地时间”(除非您在阅读后明确将其转换为时区)。

【讨论】:

  • 我确实想这样做,但如果我运行:select EXTRACT(TIMEZONE FROM timestamp with time zone '1911-03-01 00:00 -8:00:00'), timestamp with time zone '1911-03-01 00:00 -8:00:00';,结果是:0;"1911-03-01 08:00:00+00" - 它丢失了时区信息,这就是我问这个问题的原因。如何将此偏移信息存储在 timestamp with time zone 中?
  • 你不能在 PG 中。时间戳总是在没有时区或偏移量的情况下存储(时区或偏移量仅用于将其转换为读取或写入)。是的,这很令人困惑,但是日期时间管理很复杂。阅读我在 cmets 中的链接答案。
  • 那么,就我而言,我是否最好总是使用at time zone 'UTC' 进行查询,以便在任何地方获得一个标准化时间并将偏移量存储在另一列中以呈现本地时间?
【解决方案3】:

时区因各种原因而变化。

夏令时规则发生变化。

如果各国出于政治原因重新定义其时区,有时时区偏移也会发生变化。

规范的时区信息数据库是the tz or "zoneinfo" database,以前叫奥尔森数据库。 The zoneinfo DB is on the IANA site。有多种programs to dump human readable versions of the DB

如果您希望将特定时刻存储在挂钟时间中,您可以使用timestamp without time zone,而无需考虑时区。

timestamp with time zone 对系统 TimeZone 的输入和输出设置敏感,并以 UTC 时间存储为绝对秒数。所以它被转换为输入和输出。如果您想要不同的转换或覆盖转换,您可以使用AT TIME ZONE 运算符。

【讨论】:

  • 所以我可以说:select timestamp with time zone '1911-03-01 00:00 -8:00:00' at time zone 'UTC';,这确实给了我正确的结果1911-03-01 08:00:00。但是,我还想提取当时与时间戳相关的偏移量。当我尝试它时,就像问题一样,它给了我 0。如何以这种方式配置 zoneinfo 来做到这一点? this 不是说第 406 行应该是 -7:52:58 吗?否则,它是否以某种方式基于我当地时区的伦敦时间?
  • @WilliamBecker 不,时间戳在输入时转换。 TZ 偏移量没有保留,也没有办法保留,以后再提取。如果您希望保留 TZ 偏移量,则必须单独存储它。是的,这违反直觉。
【解决方案4】:

确实取决于您的时区。 1966 年,DST was first implemented nationally in the US 将在 1967 年发生。各州需要通过法律来结束它,这意味着在许多地区,1967 年是唯一使用 DST 的一年。这可能会导致一些非常有趣的故障,除 1967/68 之外的每个日期都正常运行。

【讨论】:

    猜你喜欢
    • 2017-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-25
    • 2021-12-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多