2012-12-12 17 views

Odpowiedz

21

Niestety PostgreSQL nie oferuje typ danych strefy czasowej, więc powinieneś używać text.

interval wydaje się być logiczną opcją na pierwszy rzut oka, a dla niektórych zastosowań jest to , czyli. Nie uwzględnia jednak czasu letniego, ani nie bierze pod uwagę faktu, że różne regiony w tym samym offsecie UTC mają różne reguły DST.

Nie ma odwzorowania 1: 1 od przesunięcia UTC do strefy czasowej.

Na przykład, strefa czasowa Australia/Sydney (Nowa Południowa Walia) UTC+10 (EST) lub UTC+11 (EDT) podczas czasu letniego. Tak, to ten sam akronim, którego używa USA; akronimy strefy czasowej są nieunikalne w bazie danych tzdata, dlatego też Pg ma ustawienie timezone_abbreviations. Co gorsza, Brisbane (Queensland) ma prawie taką samą długość i jest w UTC+10 EST ... ale nie ma oszczędności na świetle dziennym, więc czasami jest to przesunięcie do Nowej Południowej Walii podczas DST NSW.

(Aktualizacja: Niedawno Australia przyjęła A prefiks, więc używa AEST jako jej wschodnich stanach TZ akronimem, ale EST i WST pozostają w powszechnym użyciu).

Mylące dużo?

Jeśli wszystko, czego potrzebujesz do przechowywania, to przesunięcie UTC, wtedy odpowiedni jest interval. Jeśli chcesz zapisać strefę czasową , zapisz ją jako text. To jest trudność do sprawdzenia i przejścia na przesunięcie strefy czasowej w tym momencie, ale przynajmniej radzi sobie z DST.

+1

Czy istnieje link do kanonicznych ciągów tekstowych (Australia/Sydney) dla wszystkich stref czasowych? – odigity

+1

Tak: http://en.wikipedia.org/wiki/List_of_tz_database_time_zones – odigity

+0

Jeśli chcesz zoptymalizować wydajność + oszczędność miejsca (i zmniejszyć przenośność/elastyczność), baza danych tz + enum byłaby dobra –

1

może przedział

 
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" i "-hh: mm" nie są strefami czasowymi, są to przesunięcia UTC. Dobry format do zapisania są jako liczba całkowita ze znakiem z przesunięciem w minutach. Możesz także użyć rzeczy takich jak interval, ale to tylko ci pomoże, jeśli chcesz wykonywać obliczenia daty bezpośrednio w PostgreSQL, jak w zapytaniu, itp. Zwykle, jeśli robisz te obliczenia w innym języku, a potem to zależy od tego języka, jeśli dobrze obsługuje typ typu interval i ma dobrą bibliotekę daty/czasu lub nie. Ale konwersja liczby całkowitej na rodzaj typu podobnego do interval powinna być trywialna, więc osobiście po prostu zapisałbym ją jako liczbę całkowitą.

Strefy czasowe mają nazwy i chociaż nie ma znormalizowanych nazw stref czasowych, w bazie danych "tz" lub "zoneinfo" znajduje się jeden de facto standard, a nazwy takie jak "Europa/Paryż", "Ameryka/New_York "lub" US/Pacific ". Te powinny być przechowywane jako ciągi.

System Windows używa zupełnie innych nazw, np. "Czas na romans" (nie pytaj). Możesz przechowywać je tak samo jak napisy, ale uniknęłbym ich, nazwy te nie są używane poza Windows, a nazwy nie mają sensu.Poza tym przetłumaczone wersje okien mają tendencję do używania przetłumaczonych nazw dla tych stref czasowych, co czyni je jeszcze gorszymi.

Skróty takie jak "PDT" i "EST" nie nadają się do użytku jako nazwy stref czasowych, ponieważ nie są unikalne. Istnieją cztery (jak sądzę, czy może pięć?) Różne strefy czasowe, wszystkie nazywane "CST", więc nie można ich użyć.

W skrócie: w przypadku stref czasowych należy zapisać nazwę jako ciąg. W przypadku przesunięć UTC przechowaj przesunięcie w minutach jako liczbę całkowitą ze znakiem.

+0

Czy istnieje link do tekstu kanonicznego ciągi (Australia/Sydney) dla wszystkich stref czasowych? – odigity

+0

Tak: http://en.wikipedia.org/wiki/List_of_tz_database_time_zones – odigity

4

W idealnym świecie możesz mieć klucz obcy do zestawu znanych stref czasowych. Możesz zrobić coś zbliżonego do tego z widokami i domenami.

Ten wiki tip przez Davida E. Wheleer tworzy domenę, która jest testowana pod kątem jej ważności jako Strefa czasowa:

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)); 

Jest to użyteczne, aby mieć listę znanych stref czasowych, w którym to przypadku można zrezygnować z domeny i po prostu wymusić ograniczenia w jednej tabeli zawierającej znane nazwy strefy czasowej (uzyskane z punktu widzenia pg_timezone_names), unikając konieczności narażać domenę w innym miejscu:

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; 

Następnie można wymusić poprzez języków obcych? Raczej poprawności Klawisze gn:

CREATE TABLE myTable (
... 
tzone TEXT REFERENCES tzone(tzone_name) 
); 
Powiązane problemy