如何使用AT TIME ZONE选择带偏移量的时间戳

时间:2018-03-09 11:57:17

标签: sql postgresql datetime select timezone-offset

我在PostgreSQL中填写时间戳,阅读有关此行为的有趣Blog,但无法解决以下问题:

如何从另一列选择带有AT TIME ZONE的'带时区的'时间戳'列,包括一步到达UTC的偏移量?

我在PostgreSQL 10中有一个示例表:

CREATE TABLE public.test_tz
(
    id serial,
    in_zone_timestamp timestamp without time zone,
    in_zone character varying COLLATE pg_catalog."default",
    CONSTRAINT test_tz_pkey PRIMARY KEY (id)
)
WITH (
    OIDS = FALSE
)
TABLESPACE pg_default;

PostgreSQL的设置是

  

时区=本地时间

并且服务器在'Europe / Berlin'

运行
  

$ date - > 3月9日星期五12:15:23 CET 2018

timestamp列应该存储这种凌乱的语法:

INSERT INTO public.test_tz ( in_zone_timestamp, in_zone) VALUES
('2017-02-01 00:00:00' AT TIME ZONE current_setting('TIMEZONE') AT TIME ZONE 'Asia/Singapore', 'Asia/Singapore' );

如果有人知道更好的方法,请不要退缩!另一个解决方案是使用'2017-02-01 00:00:00-08'作为值,但我不知道偏移值。

我想存储本地时间戳,例如:'用户在新加坡的2017-02-01 00:00:00点击了一个键'。

如果我问数据库:在欧洲的哪个时间,当新加坡的用户点击密钥时,我得到了:

SELECT in_zone_timestamp FROM public.test_tz;
--> '2017-01-31 17:00:00+01'

这似乎没问题,因为新加坡的偏差为+8小时。

如果我想知道,在新加坡的哪个时间,我使用:

SELECT in_zone_timestamp AT TIME ZONE in_zone FROM public.test_tz;
--> '2017-02-01 00:00:00'

也没关系,但是,它没有将偏移量返回到'UTC',所以我看不到这个时间戳不在我当地时间!

我尝试AT TIME ZONE的某些组合或转换为timestamptz,但结果不是我想要的。我期待得到一个结果:

--> '2017-02-01 00:00:00+08'

在这里,我只看到一个解决方案,手动连接/转换/操纵结果并手动添加偏移量,但这是唯一的方法吗?

很抱歉,如果我解释这个问题有点过于复杂,希望有人能听从我的想法。

提前致谢

2 个答案:

答案 0 :(得分:1)

让PostgreSQL自动将时间戳转换为2017-02-01 00:00:00+08这样的字符串的唯一方法是更改​​会话时区:

SET timezone = 'Asia/Singapore';

您可以使用SET LOCAL仅在交易期间更改设置。

如果您不想这样,可以使用如下查询获取偏移量:

SELECT TIMESTAMP '2000-01-01 00:00:00' AT TIME ZONE 'UTC'
     - TIMESTAMP '2000-01-01 00:00:00' AT TIME ZONE 'Asia/Singapore';

 ?column? 
----------
 08:00:00
(1 row)

答案 1 :(得分:1)

感谢澄清,但在我看来,PostgreSQL在这个主题上有一些缺点。

A'不太完美'这个问题的解决方案实际上是手动连接所需的部件。

SELECT (test_tz.in_zone_timestamp AT TIME ZONE in_zone) || (SELECT abbrev FROM pg_timezone_names WHERE name = in_zone)  FROM public.test_tz;
--> 2017-02-01 00:00:00+08

这提供了一个可接受的解决方案,具有很小的缺陷。

在某些情况下,缩写栏中有时区短文,例如' CET'或者' PDT'而不是+/-数值。这会产生结果(例如,对于欧洲/柏林'),例如:

--> 2017-02-01 02:00:00CET

更好的值会给列'utc_offset' pg-timezone-names的{{3}},但这需要更复杂的文本处理,我现在不想要。

第二种解决方案可以是通过应用程序操作输出并将文本格式化为您需要的任何内容。

希望帮助其他人解决此类问题,而无需在互联网上搜索数据库中没有的支持。

再见

相关问题