sai*_*heg 48 postgresql timezone
今天早上我遇到了以下问题:
select '2011-12-30 00:30:00'::timestamp without time zone AT TIME ZONE 'EST5EDT';
Run Code Online (Sandbox Code Playgroud)
回报我2011-12-30 05:30:00+00女巫是错的.
但下面的查询如下:
select '2011-12-30 00:30:00'::timestamp without time zone AT TIME ZONE 'UTC-5';
select '2011-12-30 00:30:00' AT TIME ZONE 'EST5EDT';
Run Code Online (Sandbox Code Playgroud)
我看到了正确的约会 2011-12-29 19:30:00
防止您对我当地时区的提问:
SELECT current_setting('TIMEZONE');
current_setting
-----------------
UTC
(1 row)
Run Code Online (Sandbox Code Playgroud)
有没有人回答为什么postgresql会转换timestamp without time zone一些奇怪的方式而不是带走5个小时呢?
Cra*_*ger 122
timestamp without time zone AT TIME ZONE 为了将其转换为UTC,将 a 重新解释timestamp为该时区.
timestamp with time zone AT TIME ZONE 在指定的时区将 a 转换timestamptz为a timestamp.
PostgreSQL使用ISO-8601时区,指定格林威治东部为正...除非您使用POSIX时区说明符,在这种情况下它遵循POSIX.精神错乱随之而来.
SQL中的时间戳和时区非常糟糕.这个:
select '2011-12-30 00:30:00'::timestamp without time zone AT TIME ZONE 'EST5EDT';
Run Code Online (Sandbox Code Playgroud)
将未知类型的文字解释'2011-12-30 00:30:00'为timestamp without time zone,除非另有说明,否则Pg假定它位于本地TimeZone中.当您使用AT TIME ZONE,它是(根据规格)重新解释为timestamp with time zone在该时间段EST5EDT,然后存储在UTC绝对时间-所以它的转换从 EST5EDT 到 UTC,即区偏移量被减去.x - (-5)是x + 5.
此时间戳调整为UTC存储,然后根据您的服务器TimeZone设置进行调整以便显示,以便以当地时间显示.
如果你想说"我有这个时间戳在UTC时间,并希望看到EST5EDT中的等效本地时间是什么",如果你想独立于服务器TimeZone设置,你需要写如下:
select TIMESTAMP '2011-12-30 00:30:00' AT TIME ZONE 'UTC'
AT TIME ZONE 'EST5EDT';
Run Code Online (Sandbox Code Playgroud)
这表示"给定时间戳2011-12-30 00:30:00,在转换为timestamptz时将其视为UTC时间戳,然后将该时间戳转换为EST5EDT中的本地时间".
太可怕了,不是吗?我想和那些决定疯狂语义的人交谈AT TIME ZONE - 它应该真的像timestamp CONVERT FROM TIME ZONE '-5'和timestamptz CONVERT TO TIME ZONE '+5'.此外,timestamp with time zone实际上应该携带它的时区,而不是以UTC格式存储并自动转换为本地时间.
你原来的"作品"版本:
select '2011-12-30 00:30:00' AT TIME ZONE 'EST5EDT';
Run Code Online (Sandbox Code Playgroud)
只有在TimeZone设置为UTC时才会正确,因为当未指定timeZone时,text-to-timestamptz强制转换假设为TimeZone.
两个问题相互抵消了.
看起来有效的另一个版本是TimeZone独立的,但它只能起作用,因为两个问题会自行取消.首先,如上所述,将时间戳timestamp without time zone AT TIME ZONE 重新解释为在该时区内转换为UTC时间戳; 这有效地减去了时区偏移量.
但是,由于我无法理解的原因,PostgreSQL使用带有反向符号的时间戳到我以前看到的大多数地方.查看文档:
另外要记住的一个问题是,在POSIX时区名称中,正偏移用于格林威治以西的位置.在其他地方,PostgreSQL遵循ISO-8601惯例,正面时区偏移位于格林威治以东.
这意味着它EST5EDT是相同的+5,而不是-5.这就是为什么它的工作原理:因为你减去tz偏移而不是添加它,但是你减去了一个否定的偏移量!
相反,你需要做的就是:
select TIMESTAMP '2011-12-30 00:30:00' AT TIME ZONE 'UTC'
AT TIME ZONE '+5';
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
30770 次 |
| 最近记录: |