【问题标题】:Specify a time zone to use as the reference time zone指定一个时区作为参考时区
【发布时间】:2012-02-04 11:59:44
【问题描述】:

根据前两个答案,问题与最初发布的一样不清楚,因此我完全重写它:

以下问题仅与存储数据的方式和内容有关,与检索时转换数据无关。因此,在 SELECT 转换到所需的时区不是一个合适的答案。

将值插入带时区的时间戳字段时,将检索(并因此可能存储)该值,并在插入时将时间戳转换为数据库的本地时区。

也就是说,插入为2012-01-01 00:00:00+00:00 的时间戳被检索为2011-12-31 19:00:00-05,其中插入时数据库的本地时区为-05。使用-04 时区返回在夏时制期间插入的时间戳,当时数据库位于-04

我想要的是所有时间戳在存储时使用任意时区(因此所有时间戳都可以在没有任何额外工作的情况下检索到该时区)。也就是说,如果服务器绕地球运行,那么所有时间都将在+00:00(任意时区),而不是-12:00+12:00

我可以插入带有时区的时间戳列,以便所有时间戳都相对于任意时区存储吗?如果有,怎么做?


原文如下。

将值插入timestamp with time zone 字段时,将转换为服务器的当前时区。

示例:如果我插入一个指定时区-1 的值,检索它将返回-5 的时间(插入时服务器的时区)。

是否可以指定使用任意时区存储?

注意:这个问题不是如何将返回的时间转换为另一个时区,这是特定于时间是如何存储的。

【问题讨论】:

    标签: postgresql timezone


    【解决方案1】:

    除了timestamp,您还必须保存时区偏移

    正如@Milen 已经解释的(并链接到manual):timestamp 仅保存一个时间点(作为抽象值)。时区修饰符保存,它仅用于调整 timestamp 相对于 UTC

    考虑以下演示:

    -- DROP TABLE tbl;
    CREATE TEMP TABLE tbl (id int, myts timestamptz, mytz interval);
    
    INSERT INTO tbl VALUES
     (1, now()                , EXTRACT (timezone from now()) * interval '1s')
    ,(2, '2012-01-01 00:00-05', interval '-5h')
    ,(3, '2012-01-01 00:00+04', interval '4h')
    ,(4, '2012-11-11 20:30+03', interval '3h');
    
    SELECT *
          ,(myts AT TIME ZONE mytz)::text
           || CASE WHEN mytz > '0:0' THEN '+' ELSE '' END
           || to_char(mytz, 'FMHH24:mi') AS timestamp_at_origin
    FROM tbl;
    

    在本地运行看看。请特别注意AT TIME ZONE 构造的细节,以及我如何从(本地!)timestamp with time zone 中提取时区。
    now() 返回timestamp with time zone 或简称timestamptz

    EXTRACT (timezone from now()) * interval '1s'
    

    timestamp_at_origin 显示带有时区的时间戳,如其来源所示。如果我理解你的问题,那么这就是你要找的。
    您可以进一步改进格式。

    您可能对related question 感兴趣,它揭示了时区的歧义和陷阱。

    【讨论】:

      【解决方案2】:

      将值插入timestamp with time zone 字段时,实际发生的情况是将时间戳转换为UTC。另一个问题是该值在输出时转换到哪个时区。有几种方法可以控制:

      当一个带有时区值的时间戳被输出时,它总是 从 UTC 转换为当前时区,并显示为 该区域的当地时间。要查看另一个时区的时间,要么 更改时区或使用 AT TIME ZONE 构造(请参阅Section 9.9.3)。

      【讨论】:

        【解决方案3】:

        您可以使用at time zone 运算符进行选择:

        select insertTs at time zone 'CST' from table
        

        查看更多here

        【讨论】:

          【解决方案4】:

          我总是将时间存储在 GMT 中,以便客户端可以根据当前的 GMT 偏移量进行转换(大多数语言都提供 GMT 偏移量)。

          我编写 C# - 因此我可以在数据库中存储数据时使用 DateTime.ToUniversalTime() 轻松地将所有 DateTime 对象转换为 GMT。

          我不确定您使用的是什么语言或如何在 postgressql 中将所有时间转换为 GMT,但从逻辑的角度来看 - 将所有时间存储在 GMT 中将允许所有其他时区可以轻松关联的统一时区。

          希望这会有所帮助!

          Greenwich Mean Time

          【讨论】:

            猜你喜欢
            • 2014-09-07
            • 2015-11-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-10-27
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多