我刚刚花了一个小时对这两个表达式的这些结果的差异感到绝望:
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
显然,第二个表达式根据 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
我查阅了有关时区的 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 Squeeze 上的 PostgreSQL 9.1.4(来自http://backports.debian.org/debian-backports的标准挤压反向端口)
本地
timezone
设置默认为系统 localede_AT.UTF-8
,但应该与示例无关。
SELECT version();
version
-------------------------------------------------------------------------------------------------------
PostgreSQL 9.1.4 on x86_64-unknown-linux-gnu, compiled by gcc-4.4.real (Debian 4.4.5-8) 4.4.5, 64-bit
SHOW timezone_abbreviations;
timezone_abbreviations
------------------------
Default
..(我假设)从这个文件加载缩写:/usr/share/postgresql/9.1/timezonesets/Default
我不知道时区名称CET
的来源。但显然它存在于我的装置中。对 sqlfiddle的快速测试显示了相同的结果。
我在具有类似设置的两台不同服务器上进行了测试。还有 PostgreSQL 8.4。在所有这些中找到“CET”作为时区名称。pg_timezone_names