【问题标题】:Subtracting two columns of type timestamp with time zone用时区减去两列时间戳类型
【发布时间】:2018-10-17 19:10:01
【问题描述】:

我正在将一些列类型从 TIMESTAMP WITHOUT TIME ZONE 转换为 TIMESTAMP WITH TIME ZONE

系统中已经存在的一些函数通过简单地执行以下操作来计算两个时间戳之间的差异:timestamp1 - timestamp2。

我想知道这种方法在处理时区时是否正确。 我正在考虑的解决方案如下:

timestamp1 at time zone 'America/Sao_Paulo' - timestamp2 at time zone 'America/Sao_Paulo'

但问题是:这种方法能正确处理 DST 更改吗?以这种方式减去带时区的时间戳是否安全?

谢谢!

【问题讨论】:

    标签: postgresql


    【解决方案1】:

    那不安全。考虑这个例子:

    SELECT TIMESTAMPTZ '2018-02-18 02:00:00+00' AT TIME ZONE 'America/Sao_Paulo'
         - TIMESTAMPTZ '2018-02-18 01:00:00+00' AT TIME ZONE 'America/Sao_Paulo';
    
     ?column? 
    ----------
     00:00:00
    (1 row)
    

    这是因为这些不同的绝对时间戳在那个时区看起来是一样的。 timestamp without time zone 的日期算术不正确,因为差异取决于时区。

    要找出两个timestamp with time zone 值之间的经过时间,只需将它们相减即可:

    SELECT TIMESTAMPTZ '2018-02-18 02:00:00+00'
         - TIMESTAMPTZ '2018-02-18 01:00:00+00';
    
     ?column? 
    ----------
     01:00:00
    (1 row)
    

    结果总是正确的,因为使用了绝对时间。

    【讨论】:

    • 但是如果我简单地减去它们,Postgres 怎么知道 1 天有多长?由于 DST 更改,1 天可能有 23 小时。这个简单的减法将涵盖那种情况?我不明白这是怎么回事。
    • 如果您存储timestamp with time zone,则 DST 是相关的,因为在内部一切都以 UTC 完成。尝试SET timezone = 'America/Sao_Paulo';,然后尝试SELECT TIMESTAMP '2018-02-19 00:00:00'::timestamptz - TIMESTAMP '2018-02-17 00:00:00'::timestamptz;。这是正确的结果,因为这两天花了 49 小时。
    • 你是对的!效果很好,谢谢。但我仍然不知道如何应用时区信息不起作用,并且在使用 UTC 时它会考虑到不同时间的日子。
    • 我试图在我的回答中解释它。当您转换为 timestamp with time zone 时,timezone 的当前设置用于计算该时间戳在绝对时间中的含义。
    • 我又在考虑这个解决方案。因此,当我们减去 TIMESTAMPTZ 时,它使用当前会话时区来计算 DST 更改,对吗?这基本上是我所有问题的重点,根据您的回答,我仍然不知道这个减法将如何使用 'America/Sao_Paulo' 来计算 DST 或我选择的任何其他 tz(在这种情况下是客户的 tz)。
    猜你喜欢
    • 2011-04-02
    • 1970-01-01
    • 1970-01-01
    • 2014-04-25
    • 1970-01-01
    • 2015-12-22
    • 2017-06-17
    • 1970-01-01
    • 2017-06-07
    相关资源
    最近更新 更多