영역 이름 PostgreSQL 버그가있는 "AT TIME ZONE"?


12

stackoverflow 질문에 대답하고 이상한 결과를 찾았습니다.

 select * from  pg_timezone_names where name = 'Europe/Berlin' ;
     name      | abbrev | utc_offset | is_dst 
---------------+--------+------------+--------
 Europe/Berlin | CET    | 01:00:00   | f

다음 질문

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

PostgreSQL 9.1.2 및 우분투 12.04를 사용하고 있습니다.
8.2.11의 결과가 같은지 확인했습니다.

문서 에 따르면 이름이나 약어를 사용하더라도 중요하지 않습니다.

이것이 버그입니까?
내가 뭔가 잘못하고 있습니까?
누군가이 결과를 설명 할 수 있습니까?

편집 CET이 유럽 / 베를린이 아니라는 의견.

pg_timezone_names에서 값을 선택하고 있습니다.

select * from  pg_timezone_names  where abbrev ='CEST';
 name | abbrev | utc_offset | is_dst 
------+--------+------------+--------

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
 .....

겨울철 유럽 / 베를린은 +01입니다. 여름에는 +02입니다.

EDIT2 2012-10-28 시간대는 서머 타임에서 겨울 타임으로 2:00에 변경되었습니다.
이 두 레코드는 유럽 / 베를린에서 동일한 값을 갖습니다.

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

이것은 큰 데이터 범위 (여름 시간과 겨울 시간)에 약어 (CET 또는 CEST) 중 하나를 사용하면 일부 레코드의 결과가 잘못 될 수 있음을 나타냅니다. '유럽 / 베를린'을 사용하면 좋을 것입니다.

시스템 시간을 '2012-01-17'로 변경했으며 pg_timezone_names도 변경되었습니다.

select * from  pg_timezone_names  where name ='Europe/Berlin';
     name      | abbrev | utc_offset | is_dst 
---------------+--------+------------+--------
 Europe/Berlin | CEST   | 02:00:00   | t

1
2012-10-28 01:30:00CET이 아닌 CEST 임을 확신합니다 .
dezso

1
내가 아는 한 CET것입니다 하지 Europe/Berlin - 적어도하지 DST 시간 동안.
a_horse_with_no_name

답변:


9

실제로 설명서에는 표준 시간대 이름과 약어가 다르게 동작한다고 명시되어 있습니다.

간단히 말해 이것은 약어와 전체 이름의 차이입니다. 약어는 항상 UTC로부터 고정 된 오프셋을 나타내지 만 대부분의 전체 이름은 현지 일광 절약 시간제 규칙을 나타내므로 두 가지 가능한 UTC 오프셋이 있습니다. 참고

FWIW, 그 같은 참조도 말합니다

표준 시간대와 함께 표준 시간대를 사용하지 않는 것이 좋습니다 (레거시 응용 프로그램 및 SQL 표준 준수를 위해 PostgreSQL에서 지원하지만).


6

그리고 그것은 여전히 ​​그것의 요지가 아닙니다! 나는 우연히 매우 비슷한 문제가 몇 시간 전에.

표준 시간대 약어의 주요 단점은 이미 여기에 제시되어 있습니다. DST (일광 절약 시간제)를 고려하지 않았습니다. 주요 장점 : 단순성으로 인해 우수한 성능을 제공 합니다. DST 규칙을 고려하면 표준 시간대 이름이 느려집니다 . 표준 시간대 약어는 단순하고 상징적 인 시간 오프셋이며 표준 시간대 이름은 지속적으로 변경되는 규칙을 따릅니다. SO 에 대한 관련 답변에서 벤치 마크를 실행했는데 그 차이가 현저합니다. 세트에 적용될 때, 그것은 일반적이다 필요한 행 당 아마도 다른 DST 상태 (도 역사의 차이)를 커버하는 시간대 이름을 사용 할 수 있습니다.

우리는 CET 에 대해 이야기하고 있습니다. 정말 까다로운 부분은 "CET는"뿐만 아니라 (명백하게) 인 것입니다 시간대 약어 , 그것이 또한 시간대 이름 , 적어도 de_AT.UTF-8 로케일을 데비안 짜기 "내 설치 (PostgreSQL의 9.1.6에 따라 ")와 내가 지금까지 본 다른 모든 것. Postgres는 사용 가능한 경우 기본 OS의 로캘 정보를 사용하기 때문에 이러한 세부 사항을 언급합니다.

직접 참조하십시오 :

SELECT * FROM pg_timezone_names WHERE name = 'CET';

SELECT * FROM pg_timezone_abbrevs WHERE abbrev = 'CET';

SQL 바이올린.

Postgres는 전체 이름 대신 약어를 선택합니다. 따라서 시간대 이름 에서 CET을 찾았지만 표현식 '2012-01-18 01:00 CET'::timestamptz시간대 약어에 대해 미묘하게 다른 규칙에 따라 해석됩니다 .

그것이 장전 된 권총이 아니라면 나는 무엇인지 모른다.

모호성을 피하려면 시간대 이름 'Europe / Berlin'(또는 내 경우에는 'Europe / Vienna')을 사용하십시오. 이는 역사적 차이를 제외하고는 사실상 동일합니다. 위에서 언급 한 밀접한 관련 질문 에서 해당 주제에 대한 자세한 내용을 찾아보십시오 .

마지막으로, DST의 도덕적 개념에 대한 깊은 경의를 표하고 싶습니다. 그것은 존재에서 제거되어야하고 다시는 말하지 않아야합니다.


3

이것을 확인하십시오 :

select  
    '2012-10-28 02:30:00+02'::timestamp with time zone at time zone 'Europe/Berlin' as berlin,
    '2012-10-28 02:30:00+02'::timestamp with time zone at time zone 'CET' as cet,
    '2012-10-28 02:30:00+02'::timestamp with time zone at time zone 'CEST' as cest

+02 CET이 아닌 베를린에서 CEST입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.