Eu estava respondendo a esta pergunta do stackoverflow e encontrei um resultado estranho:
select * from pg_timezone_names where name = 'Europe/Berlin' ;
name | abbrev | utc_offset | is_dst
---------------+--------+------------+--------
Europe/Berlin | CET | 01:00:00 | f
e próxima consulta
select id,
timestampwithtimezone,
timestampwithtimezone at time zone 'Europe/Berlin' as berlin,
timestampwithtimezone at time zone 'CET' as cet
from data ;
id | timestampwithtimezone | berlin | cet
-----+------------------------+---------------------+---------------------
205 | 2012-10-28 01:30:00+02 | 2012-10-28 01:30:00 | 2012-10-28 00:30:00
204 | 2012-10-28 02:00:00+02 | 2012-10-28 02:00:00 | 2012-10-28 01:00:00
203 | 2012-10-28 02:30:00+02 | 2012-10-28 02:30:00 | 2012-10-28 01:30:00
202 | 2012-10-28 02:59:59+02 | 2012-10-28 02:59:59 | 2012-10-28 01:59:59
106 | 2012-10-28 02:00:00+01 | 2012-10-28 02:00:00 | 2012-10-28 02:00:00
Estou usando o PostgreSQL 9.1.2 e o Ubuntu 12.04.
Acabei de verificar que em 8.2.11 o resultado é o mesmo.
De acordo com a documentação , não importa se eu uso nome ou abreviação.
Isso é um inseto?
Estou fazendo algo errado?
Alguém pode explicar esse resultado?
EDIT Pelo comentário de que CET não é Europa/Berlim.
Estou apenas selecionando valores de pg_timezone_names.
select * from pg_timezone_names where abbrev ='CEST';
name | abbrev | utc_offset | is_dst
------+--------+------------+--------
e
select * from pg_timezone_names where abbrev ='CET';
name | abbrev | utc_offset | is_dst
---------------------+--------+------------+--------
Africa/Tunis | CET | 01:00:00 | f
Africa/Algiers | CET | 01:00:00 | f
Africa/Ceuta | CET | 01:00:00 | f
CET | CET | 01:00:00 | f
Atlantic/Jan_Mayen | CET | 01:00:00 | f
Arctic/Longyearbyen | CET | 01:00:00 | f
Poland | CET | 01:00:00 | f
.....
Durante o inverno Europa/Berlim é +01. Durante o verão é +02.
EDIT2
Em 28/10/2012, o fuso horário mudou do horário de verão para o horário de inverno às 2:00.
Esses dois registros têm o mesmo valor na Europa/Berlim:
204 | 2012-10-28 02:00:00+02 | 2012-10-28 02:00:00 | 2012-10-28 01:00:00
106 | 2012-10-28 02:00:00+01 | 2012-10-28 02:00:00 | 2012-10-28 02:00:00
Isso sugere que, se eu usar uma das abreviações (CET ou CEST) para o intervalo de big data (horário de verão e inverno), o resultado estará errado para alguns dos registros. Será bom se eu usar 'Europe/Berlin'.
Alterei a hora do sistema para '2012-01-17' e pg_timezone_names também mudou.
select * from pg_timezone_names where name ='Europe/Berlin';
name | abbrev | utc_offset | is_dst
---------------+--------+------------+--------
Europe/Berlin | CEST | 02:00:00 | t
Na verdade, a documentação diz claramente que o nome e a abreviação do fuso horário se comportarão de maneira diferente.
FWIW, essa mesma referência também diz
E isso ainda não é o essencial! Eu me deparei com um problema muito semelhante há algum tempo.
As principais desvantagens das abreviações de fuso horário já foram apresentadas aqui: elas não levam em consideração o horário de verão (horário de verão). O principal pró: simplicidade resultando em desempenho superior . Levar em consideração as regras de horário de verão torna os nomes de fuso horário lentos em comparação. As abreviações de fuso horário são deslocamentos de tempo simbólicos simples, os nomes de fuso horário estão sujeitos a um conjunto de regras em constante mudança. Corri benchmarks nesta resposta relacionada em SO , a diferença é notável. Mas, quando aplicado a um conjunto, normalmente é necessário usar nomes de fuso horário para cobrir status de horário de verão possivelmente diferentes por linha (e também diferenças históricas).
Estamos falando do CET . A parte realmente complicada é que "CET" não é apenas (obviamente) uma abreviação de fuso horário , é também um nome de fuso horário , pelo menos de acordo com minha instalação (PostgreSQL 9.1.6 no Debian Squeeze com localidade "de_AT.UTF-8 ") e todos os outros que vi até agora. Menciono esses detalhes porque o Postgres usa as informações de localidade do sistema operacional subjacente, se disponível.
Veja por si mesmo:
SQL Fiddle.
Postgres escolhe a abreviação sobre o nome completo. Portanto, embora eu tenha encontrado CET nos nomes de fuso horário , a expressão
'2012-01-18 01:00 CET'::timestamptz
é interpretada de acordo com as regras sutilmente diferentes para abreviações de fuso horário .Se isso não é uma espingarda carregada, não sei o que é.
Para evitar ambiguidades, use o nome do fuso horário 'Europa/Berlim' (ou 'Europa/Viena' no meu caso - que é efetivamente o mesmo, exceto pelas diferenças históricas). Encontre mais detalhes sobre o tópico na pergunta intimamente relacionada que mencionei acima .
Para encerrar, gostaria de expressar meu profundo desprezo pelo conceito idiota de horário de verão. Deve ser removido da existência e nunca mais falado.
Verifique isto:
+02
é CEST em Berlim, não CET.