LÚC NÀO THỜI GIAN THỜI GIAN Có tên khu vực lỗi PostgreSQL?


12

Tôi đã trả lời câu hỏi stackoverflow này và thấy kết quả lạ:

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

và truy vấn tiếp theo

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

Tôi đang sử dụng PostgreSQL 9.1.2 và ubfox 12.04.
Chỉ cần kiểm tra rằng kết quả vào ngày 8.2.11 là như nhau.

Theo tài liệu thì không vấn đề gì nếu tôi sử dụng tên hoặc viết tắt.

Đây có phải là một lỗi?
Tôi có làm điều gì sai?
Ai đó có thể giải thích kết quả này?

EDIT Cho nhận xét rằng CET không phải là Châu Âu / Berlin.

Tôi chỉ chọn các giá trị từ 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
 .....

Trong mùa đông Châu Âu / Berlin là +01. Trong mùa hè, nó là +02.

EDIT2 Trong múi giờ 2012-10-28 đã thay đổi từ thời điểm mùa hè sang thời gian mùa đông lúc 2:00.
Hai hồ sơ này có cùng giá trị ở Châu Âu / Berlin:

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

Điều này cho thấy rằng nếu tôi sử dụng một trong những chữ viết tắt (CET hoặc CEST) cho phạm vi dữ liệu lớn (thời gian mùa hè và thời gian mùa đông) sẽ là sai đối với một số hồ sơ. Sẽ tốt nếu tôi sử dụng 'Châu Âu / Berlin'.

Tôi đã thay đổi thời gian hệ thống thành '2012-01-17' và pg_timezone_names cũng thay đổi.

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

1
Nó khá chắc chắn đó 2012-10-28 01:30:00là CEST, không phải CET.
dezso

1
Theo như tôi biết CETkhông Europe/Berlin - ít nhất là trong thời gian DST.
a_horse_with_no_name

Câu trả lời:


9

Trên thực tế, tài liệu nói rõ rằng tên múi giờ và tên viết tắt sẽ hành xử khác nhau.

Nói tóm lại, đây là sự khác biệt giữa chữ viết tắt và tên đầy đủ: chữ viết tắt luôn đại diện cho phần bù cố định từ UTC, trong khi hầu hết các tên đầy đủ ngụ ý quy tắc tiết kiệm thời gian ban ngày của địa phương và do đó có hai độ lệch UTC có thể có. Tài liệu tham khảo

FWIW, cùng tham chiếu cũng nói

Chúng tôi không khuyên bạn nên sử dụng loại thời gian với múi giờ (mặc dù nó được PostgreQuery hỗ trợ cho các ứng dụng cũ và để tuân thủ tiêu chuẩn SQL).


6

Và đó vẫn chưa phải là ý chính của nó! Tôi đã gặp một vấn đề rất giống nhau một thời gian trước đây.

Nhược điểm chính của chữ viết tắt múi giờ đã được trình bày ở đây: chúng không tính đến DST (thời gian tiết kiệm ánh sáng ban ngày). Các pro chính: đơn giản dẫn đến hiệu suất vượt trội . Việc đưa các quy tắc DST vào tài khoản làm cho tên múi giờ chậm so với. Viết tắt múi giờ là đơn giản, bù thời gian tượng trưng, ​​tên múi giờ phải tuân theo một bộ quy tắc liên tục thay đổi. Tôi đã chạy điểm chuẩn trong câu trả lời liên quan này trên SO , sự khác biệt là đáng chú ý. Nhưng khi được áp dụng cho một tập hợp, thông thường cần sử dụng tên múi giờ để bao gồm trạng thái DST khác nhau có thể trên mỗi hàng (và cả sự khác biệt lịch sử).

Chúng ta đang nói về CET . Phần thực sự khó khăn là "CET" không chỉ (rõ ràng) là viết tắt múi giờ , mà còntên múi giờ , ít nhất là theo cài đặt của tôi (PostgreQuery 9.1.6 trên Debian Squeeze với locale "de_AT.UTF-8 ") Và tất cả những người khác tôi đã thấy cho đến nay. Tôi đề cập đến các chi tiết này, bởi vì Postgres sử dụng thông tin ngôn ngữ của hệ điều hành cơ bản nếu có.

Xem cho chính mình:

SELECT * FROM pg_timezone_names WHERE name = 'CET';

SELECT * FROM pg_timezone_abbrevs WHERE abbrev = 'CET';

Câu đố SQL.

Postgres chọn tên viết tắt trên tên đầy đủ. Vì vậy, mặc dù tôi đã tìm thấy CET trong các tên múi giờ , biểu thức '2012-01-18 01:00 CET'::timestamptzđược diễn giải theo các quy tắc khác nhau tinh tế cho các chữ viết tắt múi giờ .

Nếu đó không phải là một khẩu súng ngắn nạp thì tôi không biết nó là gì.

Để tránh sự mơ hồ, hãy đi với tên múi giờ 'Châu Âu / Berlin' (hoặc 'Châu Âu / Viên' trong trường hợp của tôi - cũng thực sự giống nhau, ngoại trừ sự khác biệt lịch sử). Tìm thêm chi tiết về chủ đề dưới câu hỏi liên quan chặt chẽ mà tôi đã đề cập ở trên .

Cuối cùng, tôi muốn nói lên sự khinh bỉ sâu sắc của tôi đối với khái niệm đạo đức của DST. Nó nên được loại bỏ khỏi sự tồn tại và không bao giờ nói về một lần nữa.


3

Kiểm tra điều này:

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 là CEST ở Berlin, không phải CET.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.