为什么没有时区的日期时间格式化为有时区?
Why datetime without time zone foormatted as it have timezone?
我正在试验时区。
我的 postgres table 创建为:
Table "public.xx"
Column | Type | Collation | Nullable | Default
--------+-----------------------------+-----------+----------+---------
dtz | timestamp with time zone | | |
dt | timestamp without time zone | | |
服务器时区是'UTC'。我是从 show timezone
;
知道的
然后我插入数据:
insert into xx values( TIMESTAMP WITH TIME ZONE '2018-08-01 13:00:00+3', TIMESTAMP WITH TIME ZONE '2018-08-01 13:00:00+3' );
INSERT 0 1
tucha=> select * from xx;
dtz | dt
------------------------+---------------------
2018-08-01 10:00:00+00 | 2018-08-01 10:00:00
(1 row)
结果很容易理解:日期存储在UTC
中,因此减去3。
还要注意 dtz
有 +00
现在当我使用 at time zone
tucha=> select dtz at time zone 'UTC', dt at time zone 'UTC' from xx;
timezone | timezone
---------------------+------------------------
2018-08-01 10:00:00 | 2018-08-01 10:00:00+00
(1 row)
为没有时区的字段添加 +00
,反之亦然:dtz
字段没有 +00
。
为什么会这样?
一个简短的回答是——因为它是这样设计的:
timestamp without time zone AT TIME ZONE zone returns timestamp
with time zone
timestamp with time zone AT TIME ZONE zone returns
timestamp without time zone
更长:
正如您所说,您的客户端在 UTC 时区工作,服务器始终以 UTC 存储 timestamptz
,因此 select 时间匹配(您在任何地方都使用 UTC)。
首先 select timestamptz
与 +00
一起显示,因为这是时区感知字段 - 它会向您显示时区。 dt
对时区一无所知,因此显示 none...
现在,当您使用 AT TIME ZONE
时,您会要求在某些特定时区显示时间戳,因此时区感知数据类型会向您显示特定时区的时间(增加小时等),但在 "moving" time 它不能作为时区感知重用(因为它不再是服务器 UTC 时间),因此它隐藏了 TZ
。与不知道时区的时间相反,当在某个特定时区显示时,获得 "awareness" 并扣除它显示 +00
的时间,所以你会知道你在 TZ
上操作不知道时间戳。我认为这就是这里的逻辑。
我找到了 good article how to work with timezones (RU):
So – timestamp at time zone gives timestamptz which represents the moment in time when local time at given zone was as given.
and timestamptz at time zone gives timestamp, which shows what the time was in given timezone at given point in time.
我正在试验时区。
我的 postgres table 创建为:
Table "public.xx"
Column | Type | Collation | Nullable | Default
--------+-----------------------------+-----------+----------+---------
dtz | timestamp with time zone | | |
dt | timestamp without time zone | | |
服务器时区是'UTC'。我是从 show timezone
;
然后我插入数据:
insert into xx values( TIMESTAMP WITH TIME ZONE '2018-08-01 13:00:00+3', TIMESTAMP WITH TIME ZONE '2018-08-01 13:00:00+3' );
INSERT 0 1
tucha=> select * from xx;
dtz | dt
------------------------+---------------------
2018-08-01 10:00:00+00 | 2018-08-01 10:00:00
(1 row)
结果很容易理解:日期存储在UTC
中,因此减去3。
还要注意 dtz
有 +00
现在当我使用 at time zone
tucha=> select dtz at time zone 'UTC', dt at time zone 'UTC' from xx;
timezone | timezone
---------------------+------------------------
2018-08-01 10:00:00 | 2018-08-01 10:00:00+00
(1 row)
为没有时区的字段添加 +00
,反之亦然:dtz
字段没有 +00
。
为什么会这样?
一个简短的回答是——因为它是这样设计的:
timestamp without time zone AT TIME ZONE zone returns timestamp with time zone
timestamp with time zone AT TIME ZONE zone returns timestamp without time zone
更长:
正如您所说,您的客户端在 UTC 时区工作,服务器始终以 UTC 存储 timestamptz
,因此 select 时间匹配(您在任何地方都使用 UTC)。
首先 select timestamptz
与 +00
一起显示,因为这是时区感知字段 - 它会向您显示时区。 dt
对时区一无所知,因此显示 none...
现在,当您使用 AT TIME ZONE
时,您会要求在某些特定时区显示时间戳,因此时区感知数据类型会向您显示特定时区的时间(增加小时等),但在 "moving" time 它不能作为时区感知重用(因为它不再是服务器 UTC 时间),因此它隐藏了 TZ
。与不知道时区的时间相反,当在某个特定时区显示时,获得 "awareness" 并扣除它显示 +00
的时间,所以你会知道你在 TZ
上操作不知道时间戳。我认为这就是这里的逻辑。
我找到了 good article how to work with timezones (RU):
So – timestamp at time zone gives timestamptz which represents the moment in time when local time at given zone was as given.
and timestamptz at time zone gives timestamp, which shows what the time was in given timezone at given point in time.