“В ЧАСУ ЗОНИ” з назвою зони PostgreSQL помилка?


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 та ubuntu 12.04.
Просто перевірили, що 8.2.11 результат такий же.

Згідно з документацією, не має значення, чи використовую я ім’я або абревіатуру.

Це помилка?
Я щось роблю не так?
Чи може хтось пояснити цей результат?

EDIT Для коментаря, що CET не є Європою / Берліном.

Я просто вибираю значення з імен pg_timezone_name.

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:00це CEST, а не CET.
dezso

1
Наскільки я знаю CET, ні Europe/Berlin - принаймні, не в часи DST.
a_horse_with_no_name

Відповіді:


9

Насправді в документації чітко сказано, що назва часового поясу та абревіатура будуть вести себе по-різному.

Коротше кажучи, це різниця між абревіатурами та повними іменами: абревіатури завжди представляють собою фіксований зсув від UTC, тоді як більшість повних назв означають місцеве правило літнього часу, а отже, є два можливі компенсації UTC. Довідково

FWIW, це ж посилання також говорить

Ми не рекомендуємо використовувати час типу з часовим поясом (хоча він підтримується PostgreSQL для застарілих програм та для відповідності стандарту SQL).


6

І це ще не суть цього! Я зіткнувся з дуже подібною проблемою деякий час тому.

Тут уже представлені основні мінуси часових поясів: вони не враховують літній час (DST). Основна проблема: простота, що призводить до чудової продуктивності . Врахування правил DST враховує повільні назви часових поясів порівняно. Скорочення часових поясів - прості, символічні зміщення часу, назви часових поясів підпорядковуються постійно змінюваному набору правил. Я провів орієнтири в цій відповідній відповіді на SO , різниця надзвичайна. Але при застосуванні до набору, як правило, необхідно використовувати імена часових поясів для покриття можливо різного статусу DST на рядок (а також історичних відмінностей).

Ми говоримо про CET . Дійсно складна частина , що «CET» не тільки (очевидно) а зона скорочення часу , це також назва часового поясу , по крайней мере , в відповідно до моєї установки (PostgreSQL 9.1.6 на Debian Squeeze з локалі «de_AT.UTF-8 ") та всіх інших, яких я бачив досі. Я згадую ці деталі, оскільки Postgres використовує інформацію про місцевість базової ОС, якщо вона є.

Побачте самі:

SELECT * FROM pg_timezone_names WHERE name = 'CET';

SELECT * FROM pg_timezone_abbrevs WHERE abbrev = 'CET';

SQL Fiddle.

Postgres вибирає абревіатуру над повним найменуванням. Отже, незважаючи на те, що я знайшов CET в назвах часових поясів , вираз '2012-01-18 01:00 CET'::timestamptzінтерпретується відповідно до тонко різних правил для скорочень часових поясів .

Якщо це не завантажена підошва, я не знаю, що таке.

Щоб уникнути неясностей, вкажіть назву часового поясу "Європа / Берлін" (або "Європа / Відень" у моєму випадку - що фактично те саме, за винятком історичних відмінностей). Знайдіть більше деталей по темі під тісно пов'язаним питанням, про яке я згадував вище .

На завершення я хотів би висловити глибоке почуття зневаги до моронічної концепції 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 CEST в Берліні, а не CET.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.