我有一个简单的postgresql表,其中包含以下数据:
create table ti (
l text,
t timestamp without time zone
);
insert into ti(l, t) values ('now', now());
我使用at time zone
进行选择,我希望UTC + 5.30 hours
select now(), t, t at time zone 'Asia/Kolkata' from ti;
但这就是我得到的:
now| t| timezone
2019-06-06T12:11:42.576388Z| 2019-06-06T11:50:48.178689Z| 2019-06-06T06:20:48.178689Z
它减去了5.30小时而不是添加它们。
Sqlfiddle here
答案 0 :(得分:2)
now()返回带有时区的时间戳。当将时区信息保存到表中时,该时区信息将被转换为没有时区的时间戳,但是其中保存的实际值将取决于会话时区。
您可以很容易地看到这种行为:
postgres=# begin;
BEGIN
postgres=# set time zone utc;
SET
postgres=# insert into test select now();
INSERT 0 1
postgres=# set time zone 'US/Eastern';
SET
postgres=# insert into test select now();
INSERT 0 1
postgres=# select * from test;
a
----------------------------
2019-06-06 12:46:10.475424
2019-06-06 08:46:10.475424
(2 rows)
发表评论后再进行一些解释。我认为您遇到的问题是在时间戳和时间戳之间进行转换。如果仅坚持使用时间戳,那么时间戳就不会那么混乱了。让我们从讨论中删除now(),因为这会增加一层额外的复杂性,因为从now()的结果转换为无时区的时间戳取决于会话时区。
select '2019-06-06 12:00:00UTC'::timestamp with time zone,
('2019-06-06 12:00:00UTC'::timestamp with time zone) at time zone 'Asia/Kolkata';
timestamptz | timezone
------------------------+---------------------
2019-06-06 12:00:00+00 | 2019-06-06 17:30:00
我相信这是您的期望?我们从带有时区的时间戳转换为在特定时区的没有时区的时间戳。
尽管如此,您正在做什么:
select '2019-06-06 12:00:00UTC'::timestamp with time zone,
(('2019-06-06 12:00:00UTC'::timestamp with time zone)::timestamp without time zone) at time zone 'Asia/Kolkata';
timestamptz | timezone
------------------------+------------------------
2019-06-06 12:00:00+00 | 2019-06-06 06:30:00+00
(1 row)
我想,如果您可以存储带时区的时间戳而不是无时区的时间戳,那么您会发现混乱程度降低了。