2012-12-12 31 views

Trả lời

21

Thật không may PostgreSQL không đưa ra một kiểu dữ liệu múi giờ, vì vậy có lẽ bạn nên sử dụng text.

interval có vẻ như một lựa chọn hợp lý ở cái nhìn đầu tiên và nó thích hợp cho một số ứng dụng. Tuy nhiên, nó không xem xét thời gian tiết kiệm ánh sáng ban ngày, và cũng không xem xét thực tế là các vùng khác nhau trong cùng một bù đắp UTC có các quy tắc DST khác nhau.

Không có ánh xạ 1: 1 từ chênh lệch UTC ngược về múi giờ.

Ví dụ, múi giờ cho Australia/Sydney (New South Wales) là UTC+10 (EST), hoặc UTC+11 (EDT) trong thời gian tiết kiệm ánh sáng ban ngày. Vâng, đó là từ viết tắt EST mà Hoa Kỳ sử dụng; các từ viết tắt múi giờ không phải là duy nhất trong cơ sở dữ liệu tzdata, đó là lý do tại sao Pg có cài đặt timezone_abbreviations. Tồi tệ hơn, Brisbane (Queensland) có tuổi thọ gần như giống nhau và nằm trong số UTC+10 EST ... nhưng không có tiền tiết kiệm ban ngày, vì vậy đôi khi nó ở mức -1 được bù đắp cho New South Wales trong DST của NSW.

(Cập nhật: Gần đây hơn Úc áp dụng một tiền tố A, vì vậy nó sử dụng AEST như bang phía đông TZ viết tắt của nó, nhưng ESTWST vẫn được sử dụng phổ biến).

Khó hiểu nhiều?

Nếu tất cả những gì bạn cần lưu trữ là Giá trị UTC thì interval là thích hợp. Nếu bạn muốn lưu trữ múi giờ , hãy lưu trữ là text. Đó là một nỗi đau để xác nhận và chuyển đổi sang một khoảng thời gian bù đắp tại thời điểm này, nhưng ít nhất nó đối phó với DST.

+1

Có liên kết tới chuỗi văn bản chuẩn (Úc/Sydney) cho tất cả các múi giờ không? – odigity

+1

Có: http://en.wikipedia.org/wiki/List_of_tz_database_time_zones – odigity

+0

Nếu bạn muốn tối ưu hóa hiệu suất + tiết kiệm không gian (và giảm tính di động/linh hoạt), cơ sở dữ liệu tz + enum sẽ là tốt –

1

có lẽ khoảng

 
postgres=# select interval '01:30'; 
interval 
---------- 
01:30:00 
(1 row) 

postgres=# select interval '-01:30'; 
interval 
----------- 
-01:30:00 
(1 row) 
9

"+ hh: mm" và "-hh: mm" không phải là múi giờ, chúng là khoảng bù UTC. Một định dạng tốt để lưu chúng là một số nguyên có chữ ký với độ lệch trong vài phút. Bạn cũng có thể sử dụng những thứ như interval nhưng điều đó sẽ chỉ giúp bạn nếu bạn muốn thực hiện các phép tính ngày trực tiếp trong PostgreSQL, như trong truy vấn, v.v. Thông thường bạn thực hiện các phép tính này bằng ngôn ngữ khác, và sau đó phụ thuộc vào ngôn ngữ đó hỗ trợ các loại interval tốt và có một thư viện ngày/giờ tốt hay không. Nhưng chuyển đổi một số nguyên thành một số loại interval -như loại, như Pythons timedelta nên tầm thường, vì vậy tôi sẽ cá nhân chỉ lưu trữ dưới dạng số nguyên.

Múi giờ có tên và mặc dù không có tên chuẩn cho múi giờ có một tiêu chuẩn thực tế trong cơ sở dữ liệu "tz" hoặc "zoneinfo" và đó là tên "Châu Âu/Paris", "Châu Mỹ/New_York "hoặc" US/Pacific ". Chúng phải được lưu trữ dưới dạng chuỗi.

Windows sử dụng các tên hoàn toàn khác nhau, chẳng hạn như "Thời gian lãng mạn" (không hỏi). Bạn có thể lưu trữ chúng cũng như các chuỗi, nhưng tôi sẽ tránh nó, những cái tên này không được sử dụng bên ngoài Windows và những cái tên đó không có ý nghĩa gì cả.Bên cạnh đó, phiên bản dịch của các cửa sổ có xu hướng sử dụng tên dịch cho các múi giờ này, làm cho nó còn tệ hơn nữa.

Các từ viết tắt như "PDT" và "EST" không thể sử dụng làm tên múi giờ, vì chúng không phải là duy nhất. Có bốn (tôi nghĩ, hoặc là năm?) Các múi giờ khác nhau đều được gọi là "CST", vì vậy không thể sử dụng được.

Tóm lại: Đối với các múi giờ, hãy lưu tên dưới dạng chuỗi. Đối với bù trừ UTC, lưu trữ độ lệch theo phút bằng số nguyên đã ký.

+0

Có liên kết đến văn bản chuẩn chuỗi (Úc/Sydney) cho tất cả các múi giờ? – odigity

+0

Có: http://en.wikipedia.org/wiki/List_of_tz_database_time_zones – odigity

4

Trong một thế giới lý tưởng, bạn có thể có khóa ngoài cho một tập hợp các múi giờ đã biết. Bạn có thể làm một cái gì đó gần với điều này với quan điểm và tên miền.

này wiki tip David E. Wheleer tạo một tên miền mà được kiểm tra tính hợp lệ của nó như là một múi giờ:

CREATE OR REPLACE FUNCTION is_timezone(tz TEXT) RETURNS BOOLEAN as $$ 
BEGIN 
PERFORM now() AT TIME ZONE tz; 
RETURN TRUE; 
EXCEPTION WHEN invalid_parameter_value THEN 
RETURN FALSE; 
END; 
$$ language plpgsql STABLE; 

CREATE DOMAIN timezone AS CITEXT 
CHECK (is_timezone(value)); 

Nó rất hữu ích để có một danh sách các múi giờ được biết đến, trong trường hợp này bạn có thể phân chia với các tên miền và chỉ cần thực thi các hạn chế trong một bảng chứa tên múi giờ được biết đến (thu được từ quan điểm pg_timezone_names), tránh sự cần thiết phải tiếp xúc với các miền khác:

CREATE TABLE tzone 
(
    tzone_name text PRIMARY KEY (tzone_name) CHECK (is_timezone(tzone_name)) 
); 

INSERT INTO tzone (tzone_name) 
SELECT name FROM pg_timezone_names; 

Sau đó, bạn có thể thực thi đúng đắn thông qua forei gn keys:

CREATE TABLE myTable (
... 
tzone TEXT REFERENCES tzone(tzone_name) 
); 
Các vấn đề liên quan