OSX postgres 9.1.4时区,时区顺序为

时间:2012-12-19 21:42:50

标签: sql postgresql timezone

在postresql服务器9.1.4上的OSX 10.8上是一种意外行为。 因为在Ubuntu 12.04上它是正确的。

要重现此问题,请使用以下postgres sql示例数据库。 注意: 时间戳值在时间区“Europe / Berlin”中选择,时间戳在2012的DST末尾附近,这是此测试的情况。

BEGIN;
DROP TABLE data;
CREATE TABLE data (
"id" int8 NOT NULL,
"timestampwithtimezone" timestamp(6) WITH TIME ZONE,
CONSTRAINT "data_pkey" PRIMARY KEY ("id")
);
COMMIT;

BEGIN; 
INSERT INTO data (id, timestampwithtimezone) VALUES (205,'2012-10-28 01:30:00+02');
INSERT INTO data (id, timestampwithtimezone) VALUES (204,'2012-10-28 02:00:00+02');
INSERT INTO data (id, timestampwithtimezone) VALUES (203,'2012-10-28 02:30:00+02');
INSERT INTO data (id, timestampwithtimezone) VALUES (202,'2012-10-28 02:59:59+02');
INSERT INTO data (id, timestampwithtimezone) VALUES (106,'2012-10-28 02:00:00+01');
INSERT INTO data (id, timestampwithtimezone) VALUES (107,'2012-10-28 02:30:00+01');
INSERT INTO data (id, timestampwithtimezone) VALUES (108,'2012-10-28 02:59:59+01');
INSERT INTO data (id, timestampwithtimezone) VALUES (109,'2012-10-28 03:00:00+01');
INSERT INTO data (id, timestampwithtimezone) VALUES (110,'2012-10-28 03:30:00+01');
COMMIT;

如果我键入以下SQL查询,该查询仅查找给定时间戳之前的最后一个存在时间戳:

SELECT id, timestampwithtimezone at time zone 'Europe/Berlin' as timestampwithtimezone
FROM data
WHERE 
timestampwithtimezone at time zone 'Europe/Berlin' 
< cast('2012-10-28T02:30:00.000+01' AS timestamp)
ORDER BY timestampwithtimezone DESC 
LIMIT 1;

我的预期结果是:

║106║2012-10-28 02:00:00║

因为我想要在给定(2012-10-28T02:30:00.000 + 01)时间戳之前的最后一个时间戳。 但结果包含:

║204║2012-10-28 02:00:00║

在这种情况下,似乎postgresqls排序是错误的。在Ubuntu下,我得到了正确的答案,即id:106而不是204。

BUT:

如果我设置此查询:(唯一的区别是我将结果集映射删除到时区):

SELECT id, timestampwithtimezone
FROM data
WHERE timestampwithtimezone at time zone 'Europe/Berlin' 
< cast('2012-10-28T02:30:00.000+01' AS timestamp)
ORDER BY timestampwithtimezone DESC 
LIMIT 1;

OSX 10.8中的结果集与Ubuntu 12.04中的结果一样:

║106║2012-10-28 02:00:00 + 01║

为什么OS版本之间存在差异? 在这种情况下,此查询的答案“204”确实是错误的。 但是,如果我将时间戳映射到时区,为什么结果集会有差异?据我所知,postgresql使用内部UTC来存储时间戳。因此,DST应该不是时间轴中的问题。 为什么会这样?

提前致谢,希望得到答复。

1 个答案:

答案 0 :(得分:1)

以前的回答是错误的。

根据您的数据。两个答案都很好。

在2012-10-28,从夏令时到冬令时(Here it is explained)有时间变化。

查看此结果中的小时数:

select id, 
  timestampwithtimezone, 
  timestampwithtimezone at time zone 'Europe/Berlin' as berlin  
from data 
order by berlin ;


 id  | timestampwithtimezone  |       berlin        
-----+------------------------+---------------------
 205 | 2012-10-28 01:30:00+02 | 2012-10-28 01:30:00
 204 | 2012-10-28 02:00:00+02 | 2012-10-28 02:00:00
 106 | 2012-10-28 02:00:00+01 | 2012-10-28 02:00:00
 203 | 2012-10-28 02:30:00+02 | 2012-10-28 02:30:00
 202 | 2012-10-28 02:59:59+02 | 2012-10-28 02:59:59

ID为204和106的记录在柏林列中具有相同的值。

阅读here的问答。

如果您想按时间戳排序,请不要将列的别名用作同名

SELECT 
  id, 
  timestampwithtimezone at time zone 'Europe/Berlin' as timestampwithtimezone_alias
FROM data
WHERE 
  timestampwithtimezone at time zone 'Europe/Berlin' 
  < cast('2012-10-28T02:30:00.000' AS timestamp)
ORDER BY timestampwithtimezone DESC 
LIMIT 1;