存储/检索带或不带时区的时间戳

时间:2016-10-03 07:24:07

标签: postgresql datetime timestamp-with-timezone

我想测试一下与时区字段的时间戳和时间戳的差异。但是我遇到了一些我无法理解为什么会这样运作的东西。

我有以下设置:

CREATE TABLE tbl_test_timezones (
    first_date timestamp with time zone,
    second_date timestamp 
)

我插入了一些testdata:

insert into tbl_test_timezones (first_date, second_date) values (now(), now());

现在我想在选择

时检查两个字段之间的差异
select 
    first_date, 
    first_date at time zone 'Europe/Brussels' as first_date_wt, 
    second_date, 
    second_date at time zone 'Europe/Brussels' as second_date_wt
from tbl_test_timezones

which gives me the following result

first_date:     2016-10-03 07:03:16.63818+00    
first_date_wt:  2016-10-03 09:03:16.63818   
second_date:    2016-10-03 07:03:16.63818   
second_date_wt: 2016-10-03 05:03:16.63818+00

问题1

我想知道为什么second_date_wt正在做-2而不是像2nd_date_wt那样的+2?

问题2

让我们说我的应用程序将时间戳存储在时区中,并且用户希望获得带有此时间戳的记录。您是否必须为可以输入其时区的用户存储某种用户设置,并在检索时始终将其包含在选择查询中?或者您更喜欢在客户端应用程序中获取它并执行时区内容?

例如:

select start_date at time zone (
    select user_time_zone from tbl_user_settings where user_id = 2
)
from tbl_projects

或只做

select start_date 
from tbl_projects

1 个答案:

答案 0 :(得分:1)

回答问题1

这两个值有不同的含义。

first_date AT TIME ZONE 'Europe/Brussels'

答案:布鲁塞尔的挂钟在这个时间点显示了什么?

second_date AT TIME ZONE 'Europe/Brussels'

答案:布鲁塞尔的挂钟在什么时候显示出这个值?

回答问题2

执行此操作的最佳方法是将配置参数TimeZone设置为客户端应用程序的时区。然后,所有timestamp with time zone值都将显示在此时区中,timestamp without time zone值将被解释为此时区中的值:

SHOW TimeZone;

   TimeZone
---------------
 Europe/Vienna
(1 row)

SELECT
   TIMESTAMP WITH TIME ZONE '2016-10-01 00:00:00 UTC' AS "midnight at UTC",
   CAST(
      TIMESTAMP WITHOUT TIME ZONE '2016-10-01 00:00:00'
      AS TIMESTAMP WITH TIME ZONE
   ) AS "midnight local";

    midnight at UTC     |     midnight local
------------------------+------------------------
 2016-10-01 02:00:00+02 | 2016-10-01 00:00:00+02
(1 row)

SET TimeZone = 'America/Los_Angeles';

SELECT
   TIMESTAMP WITH TIME ZONE '2016-10-01 00:00:00 UTC' AS "midnight at UTC",
   CAST(
      TIMESTAMP WITHOUT TIME ZONE '2016-10-01 00:00:00'
      AS TIMESTAMP WITH TIME ZONE
   ) AS "midnight local";

    midnight at UTC     |     midnight local
------------------------+------------------------
 2016-09-30 17:00:00-07 | 2016-10-01 00:00:00-07
(1 row)