Postgresql: how to correctly create timestamp with timezone from timestamp, timezone fields
我有一个没有时区的时间戳表。
YYYY-MM-DD HH:MM:SS
和一个字段"时区",太平洋为"P",山为"M"。
我需要创建一个"带时区的时间戳"字段
鉴于我有两个字段,有没有办法正确地解释夏令时?
特别:
时间戳:2013-11-03 01:00:00
时区:"P"
将成为:2013-11-03 01:00:00-07
和
时间戳:2013-11-03 03:00:00
时区:"P"
将成为:2013-11-03 03:00:00-08
如果你考虑他们的名字,
在PostgreSQL中,两种类型都不存储值存储时的时区,但
-
当查询时,将调整
TIMESTAMPTZ 以表示与最初存储的时间相同的时刻(在世界的任何一个部分中),作为客户端配置的当前时区中的瞬间。 -
A
timestamp without time zone 将始终与客户端配置的时区相同,即使您查询它的时区不同:2013-11-03 03:00:00 表示的时刻将不明确并取决于客户端设置。
据推测,您使用
原则上,如果您与存储时间戳的时区位于相同的相对时区,则应该返回相同的值,因此如果您已将客户端设置为
你的第一个例子中的问题是已经存在一些歧义:
timestamp: 2013-11-03 01:00:00 timezone:"P" would become: 2013-11-03
01:00:00-07
如果您只是希望它在'-08'和'-07'之间切换,具体取决于该时刻的DST设置,这将自动为您完成,但您应该首先使用
这是一个保留初始时区的示例,因此您可以看到'-08'和'-07'之间的变化:
1 2 3 4 5 6 7 8 9 | SET TIME zone 'US/Pacific'; SELECT t AS"Date/Time for US/Pacific", t AT TIME zone 'UTC'"Date/Time in UTC" FROM (VALUES ('2013-11-03 00:00:00-07'::timestamptz), ('2013-11-03 01:00:00-07'::timestamptz), ('2013-11-03 02:00:00-07'::timestamptz), ('2013-11-03 03:00:00-07'::timestamptz)) AS v(t); |
结果:
1 2 3 4 5 6 | | DATE/TIME FOR US/PACIFIC | DATE/TIME IN UTC | |--------------------------|---------------------| | 2013-11-03 00:00:00-07 | 2013-11-03 07:00:00 | | 2013-11-03 01:00:00-07 | 2013-11-03 08:00:00 | | 2013-11-03 01:00:00-08 | 2013-11-03 09:00:00 | | 2013-11-03 02:00:00-08 | 2013-11-03 10:00:00 | |
不幸的是,只有你的两个字段无法处理DST更改。
当然值得阅读PostgreSQL手册的日期/时间类型部分,并注意
首先,当说结果将成为例如
也就是说,转换可以通过应用于
假设我们从
1 2 3 4 5 6 7 8 | SET TIME zone 'US/Pacific'; SELECT t AT TIME ZONE CASE z WHEN 'P' THEN 'US/Pacific' WHEN 'M' THEN 'US/Mountain' END FROM (VALUES ('2013-11-03 01:00:00'::TIMESTAMP, 'P'), ('2013-11-03 03:00:00'::TIMESTAMP, 'P') ) AS v(t,z); |
结果是:
1 2 3 4 | timezone ------------------------ 2013-11-03 01:00:00-08 2013-11-03 03:00:00-08 |
检查这是否对您有意义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | SET timezone TO 'PST8PDT'; SELECT now(); now ------------------------------- 2013-09-28 03:24:20.169189-07 SELECT ts, ts at TIME zone 'PST' AS"PST", ts at TIME zone 'PDT' AS"PDT" FROM (VALUES ('2013-11-03 01:00:00'::TIMESTAMP), ('2013-11-03 02:00:00'), ('2013-11-03 03:00:00') ) s (ts) ; ts | PST | PDT ---------------------+------------------------+------------------------ 2013-11-03 01:00:00 | 2013-11-03 01:00:00-08 | 2013-11-03 01:00:00-07 2013-11-03 02:00:00 | 2013-11-03 02:00:00-08 | 2013-11-03 01:00:00-08 2013-11-03 03:00:00 | 2013-11-03 03:00:00-08 | 2013-11-03 02:00:00-08 |