Store/Retrieve 带或不带时区的时间戳
Store/Retrieve a timestamp with or without timezone
我想测试时间戳和时间戳与时区字段的一些差异。但是我遇到了一些我无法真正理解为什么它会这样工作的东西。
我有以下设置:
CREATE TABLE tbl_test_timezones (
first_date timestamp with time zone,
second_date timestamp
)
我插入了一些测试数据:
insert into tbl_test_timezones (first_date, second_date) values (now(), now());
现在我想在执行 select
时检查两个字段之间的差异
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
问题一
我想知道为什么 second_date_wt 是 -2 而不是像 first_date_wt 那样的 +2?
问题二
假设我的应用程序将时间戳与时区一起存储,并且用户想要获取一些具有该时间戳的记录。您是否必须为用户存储某种用户设置,他可以在其中输入他的时区,并在检索时始终将其包含在 select 查询中?或者您更喜欢只获取它并在客户端应用程序中执行时区操作?
例如:
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 的答案
这两个值有不同的含义。
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)
我想测试时间戳和时间戳与时区字段的一些差异。但是我遇到了一些我无法真正理解为什么它会这样工作的东西。
我有以下设置:
CREATE TABLE tbl_test_timezones (
first_date timestamp with time zone,
second_date timestamp
)
我插入了一些测试数据:
insert into tbl_test_timezones (first_date, second_date) values (now(), now());
现在我想在执行 select
时检查两个字段之间的差异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
问题一
我想知道为什么 second_date_wt 是 -2 而不是像 first_date_wt 那样的 +2?
问题二
假设我的应用程序将时间戳与时区一起存储,并且用户想要获取一些具有该时间戳的记录。您是否必须为用户存储某种用户设置,他可以在其中输入他的时区,并在检索时始终将其包含在 select 查询中?或者您更喜欢只获取它并在客户端应用程序中执行时区操作?
例如:
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 的答案
这两个值有不同的含义。
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)