postgresql `在时区`不正确的行为?

postgresql `在时区`不正确的行为?,postgresql,timezone,Postgresql,Timezone,我有一个简单的postgresql表,其中包含以下数据: create table ti ( l text, t timestamp without time zone ); insert into ti(l, t) values ('now', now()); 我在时区使用进行选择,我希望UTC+5.30小时 select now(), t, t at time zone 'Asia/Kolkata' from ti; 但我得到的是: now| t| timezone

我有一个简单的postgresql表,其中包含以下数据:

create table ti (
  l text,
  t timestamp without time zone
  );

insert into ti(l, t) values ('now', now());
我在时区使用
进行选择,我希望
UTC+5.30小时

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

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)

在你的评论之后再解释一下。我认为您遇到的问题是时间戳和时间戳之间的转换。如果只使用timestamp,时间戳就不会那么混乱了。让我们从讨论中删除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)

我想如果你能用时区来存储时间戳,而不是不带时区的时间戳,你会发现这一点不那么令人困惑。

谢谢,我尝试了
插入ti(l,t)值('now','2019-06-06 12:00:00'),结果相同。还有时区为“UTC”的
2019-06-06 12:00:00。但是您是否首先将列定义更改为“带时区的时间戳”而不是“不带时区的时间戳”?当pg将
时间戳作为
UTC
内部存储时,为什么我必须转换两次?它不在UTC内部存储时间戳。它在内部将时间戳存储为UTC。
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