我只是花了一个小时绝望,这两个表达式的结果有差异:
db=# SELECT '2012-01-18 1:0 CET'::timestamptz AT TIME ZONE 'UTC'
,'2012-01-18 1:0 Europe/Vienna'::timestamptz AT TIME ZONE 'UTC';
timezone | timezone
---------------------+---------------------
2012-08-18 00:00:00 | 2012-08-17 23:00:00
Run Code Online (Sandbox Code Playgroud)
显然,第二个表达式根据DST规则扣除两个小时,其中第一个表达式仅使用标准偏移量.
我检查了这两个时区名称的目录.他们都在那里,看起来一样:
db=# SELECT * FROM pg_timezone_names WHERE name IN ('CET', 'Europe/Vienna');
name | abbrev | utc_offset | is_dst
---------------+--------+------------+--------
Europe/Vienna | CEST | 02:00:00 | t
CET | CEST | 02:00:00 | t
Run Code Online (Sandbox Code Playgroud)
我查阅了关于时区的PostgreSQL手册:
PostgreSQL允许您以三种不同的形式指定时区:
全时区名称,例如America/New_York.识别的时区名称列在pg_timezone_names视图中(参见第45.67节).PostgreSQL为此目的使用广泛使用的zoneinfo时区数据,因此许多其他软件也识别相同的名称.
时区缩写,例如PST.这样的规范仅定义了与UTC的特定偏移,而不是全时区名称,其也可以暗示一组夏令时转换日期规则.公认的缩写列在pg_timezone_abbrevs视图中(参见第45.66节).您不能将配置参数timezone或log_timezone设置为时区缩写,但可以在日期/时间输入值和AT TIME ZONE运算符中使用缩写.
大胆的重点我的.
为什么差异呢?
关于Debian …
我们有一个表格,里面装满了来自另一个系统的遗留报告的数据。该表的列反映了报告的相同结构。
以下是表的缩写结构:
CREATE TABLE IF NOT EXISTS LEGACY_TABLE (
REPORT_DATE DATE NOT NULL,
EVENT_ID BIGINT PRIMARY KEY NOT NULL,
START_HOUR TIMESTAMP WITHOUT TIME ZONE,
END_HOUR TIME WITHOUT TIME ZONE,
EXPECTED_HOUR TIME WITHOUT TIME ZONE
);
Run Code Online (Sandbox Code Playgroud)
我们正在重构这个表来处理不同客户端的不同时区。新结构将类似于:
CREATE TABLE IF NOT EXISTS LEGACY_TABLE (
REPORT_DATE DATE NOT NULL,
EVENT_ID BIGINT PRIMARY KEY NOT NULL,
START_HOUR TIMESTAMP WITH TIME ZONE,
END_HOUR TIME WITH TIME ZONE,
EXPECTED_HOUR TIME WITH TIME ZONE
);
Run Code Online (Sandbox Code Playgroud)
这些小时字段表示由 REPORT_DATE 列表示的一天中的特定时间点。我的意思是每个 TIME 列都代表 REPORT_DATE 中指定的一天中的一个时刻。
其他一些需要考虑的点:
我想在 postgresql 中插入时间数据类型,其中包括时区并了解夏令时。这就是我所做的:
CREATE TABLE mytable(
...
start_time time(0) with time zone,
end_time time(0) with time zone
)
INSERT INTO mytable(start_time, end_time)
VALUES(TIME '08:00:00 MST7MDT', TIME '18:00:00 MST7MDT')
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
时间类型的输入语法无效:“08:00:00 MST7MDT”
如果我使用“MST”而不是“MST7MDT”,它就可以工作,但我需要它了解夏令时。我还尝试使用“美国/埃德蒙顿”作为时区,但出现了同样的错误。
插入带有时区和 DST 的时间值(不是时间戳)的正确方法是什么?
编辑:我实际上想使用“美国/埃德蒙顿”语法