PostgreSQL时区

时间:2017-11-29 14:23:09

标签: postgresql

我正在尝试了解会话时区在PostgreSQL中的工作原理。

当我将会话时区设置为'01:00'时,返回的日期位于'-01:00'。标志总是倒置的,我不明白这种行为。

如何解释?

postgres=# set time zone '00:00';
SET
postgres=# select timestamp with time zone '2017-11-29 15:00:00.000000+00';
      timestamptz       
------------------------
 2017-11-29 15:00:00+00
(1 row)

postgres=# set time zone '01:00';
SET
postgres=# select timestamp with time zone '2017-11-29 15:00:00.000000+00';
      timestamptz       
------------------------
 2017-11-29 14:00:00-01
(1 row)

postgres=# set time zone '-01:00';
SET
postgres=# select timestamp with time zone '2017-11-29 15:00:00.000000+00';
      timestamptz       
------------------------
 2017-11-29 16:00:00+01
(1 row)

2 个答案:

答案 0 :(得分:1)

例如,这里

  • ts 是时间(文字) - 就像我们说的那样:
  • not_aware 我们不知道时区的时间(说话人的当地人)
  • 知道时间,但知道它的时区(如果服务器时区是UTC,那么是utc区域)

,所以:

s=# with s(city,tz) as (values('Moscow','UTC+3'),('New York','UTC-5'))
, ts as (select '2017-01-01 00:00:00'::text ts)
select *,ts::timestamp at time zone tz not_aware, ts::timestamptz at time zone tz aware
from s
join ts on true;
   city   |  tz   |         ts          |       not_aware        |        aware
----------+-------+---------------------+------------------------+---------------------
 Moscow   | UTC+3 | 2017-01-01 00:00:00 | 2017-01-01 03:00:00+00 | 2016-12-31 21:00:00
 New York | UTC-5 | 2017-01-01 00:00:00 | 2016-12-31 19:00:00+00 | 2017-01-01 05:00:00
(2 rows)

让我们说你来自Lodon并且拥有显示UTC0时间的手表   - 伦敦本地(这是您的服务器,时区为UTC0)。现在飞往莫斯科,看着克里姆林宫时钟,你会看到 ts ,午夜。你的手表知道时差,他们告诉你Ney Year是三个小时(这是时间戳 - 意识专栏)。这就是UTC+3要求减去时间的原因。因为对于你的服务器莫斯科时间是将来的,所以当你看到当地的2017年,对于服务器它仍然是2016年并且将会像它一样+3小时......

现在您预期的行为( not_aware 列)更棘手。服务器在UTC0运行,但必须假装它对"实时"一无所知。由于没有时区的时间戳就是这种类型。所以它表现得好像你正在电视上的红场观看新年庆祝活动而只是滚动酒吧将手表调整到克里姆林宫时钟,所以实际上你看到的时间是伦敦时间+3( not_aware )专栏。

答案 1 :(得分:0)

我在寻找其他问题的答案时遇到了这个问题。

以防万一您不明白:

  • 我认为这是试图遵循POSIX语法的时区解析代码的怪癖,如上所述。例如,您会得到相同的行为。 SET TIME ZONE 'CET1:00';SET TIME ZONE 'CET1'

  • 我认为您要说的“实际” SQL方式是SET TIME ZONE 1

  • 您可能不希望将其设置为您的时区,因为它不跟踪DST更改。您可能想要从tz数据库中按名称选择时区,例如America/New_York或(与GMT + 1示例一起使用)Europe/Madrid