【问题标题】:Confused about TIMESTAMPTZ internal conversion对 TIMESTAMPTZ 内部转换感到困惑
【发布时间】:2016-05-27 19:15:23
【问题描述】:

当谈到在 Postgres 中处理时间戳时,我花了很多时间阅读“最佳实践”,并且得到了很多相互矛盾的答案。当使用TIMESTAMPTZ 数据类型时,我假设NOW()NOW() at time zone 'utc' 会导致将相同的数据插入到数据库中。许多在线的 cmets 建议在内部实际上并未存储时区,而是转换为 UTC。

那为什么当我运行以下命令时没有得到重复的结果?

CREATE TABLE testtime(
  mytime TIMESTAMPTZ,
  descr VARCHAR
);

INSERT INTO testtime VALUES
  (NOW(), 'Now at NZST'),
  (NOW() AT TIME ZONE 'utc', 'Now at UTC');
SELECT *
FROM testtime;

结果:

2016-02-17 02:08:30.845071  Now at NZST
2016-02-16 13:08:30.845071  Now at UTC

【问题讨论】:

    标签: postgresql casting timezone timestamp


    【解决方案1】:

    原因是从timestamptimestamptz 的隐式类型转换

    • now() 返回数据类型timestamptz
    • now() AT TIME ZONE 'UTC' 返回数据类型timestamp
    • (now() AT TIME ZONE 'UTC')::timestamptztimestamp 转换为 timestamptz,在此过程中假设您当前的时区。这就是引入差异的地方。

    当您将INSERT 一个timestamp 值放入timestamptz 列时,就会发生这种情况。 Postgres 必须假设 一些 时区。您似乎已经预料到会假定 UTC。不过,更合理的默认设置是当前时区设置。如果您在会话中设置 UTC,您将获得预期的行为。

    演示:

    我的时区是“欧洲/维也纳”,目前比 UTC 早 1 小时(冬季期间):

    SET timezone = 'Europe/Vienna';
    SELECT now() AS now1
         , now() AT TIME ZONE 'UTC' AS now2
         , (now() AT TIME ZONE 'UTC')::timestamptz AS now3;
    
     现在1 |现在2 |现在3
    -------------------------------------------+------------------ ----------+-------------------
     2016-02-16 14:30:07.243082+01 | 2016-02-16 13:30:07.243082 | 2016-02-16 13:30:07.243082+01

    与 'UTC' 相同作为会话的时区设置:

    SET timezone = 'UTC';
    SELECT now() AS now1
         , now() AT TIME ZONE 'UTC' AS now2
         , (now() AT TIME ZONE 'UTC')::timestamptz AS now3;
    
     现在1 |现在2 |现在3
    -------------------------------------------+------------------ ----------+-------------------
     2016-02-16 13:30:58.739772+00 | 2016-02-16 13:30:58.739772 | 2016-02-16 13:30:58.739772+00
    

    注意前两列如何具有相同的值 - 即使now1 中的文本表示看起来不同,因为它已根据会话的时区进行了调整,但值是相同的。

    第三列有一个不同的值,因为为类型转换假定了不同的时区。

    这里的基本信息:

    【讨论】:

    • 像往常一样绝对精彩的解释。对此,我真的非常感激。谢谢。
    猜你喜欢
    • 2021-11-28
    • 1970-01-01
    • 1970-01-01
    • 2018-08-30
    • 2015-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多