2012-12-12 7 views

Antwort

21

Leider ist PostgreSQL kein Zeitzonendatentyp zur Verfügung stellen, so sollten Sie wahrscheinlich text verwenden.

interval scheint wie eine logische Option auf den ersten Blick, und es ist für einige Anwendungen geeignet. Es berücksichtigt jedoch weder die Sommerzeit noch die Tatsache, dass verschiedene Regionen in derselben UTC-Verschiebung unterschiedliche DST-Regeln aufweisen.

Es gibt kein 1: 1-Mapping von UTC-Offset zurück zur Zeitzone.

Zum Beispiel kann die Zeitzone für Australia/Sydney (New South Wales) ist UTC+10 (EST) oder UTC+11 (EDT) während der Sommerzeit. Ja, das ist das gleiche Akronym EST, dass die USA verwendet; Zeitzonenakronyme sind in der tzdata-Datenbank nicht eindeutig, weshalb Pg die timezone_abbreviations-Einstellung hat. Schlimmer noch, Brisbane (Queensland) hat fast die gleiche Länge und ist in UTC+10 EST ... aber hat keine Sommerzeit, so dass es manchmal in einem -1 Offset nach New South Wales während NSW's DST ist.

(aktualisiert: In jüngerer Zeit angenommen Australien einen A Präfix, so dass es AEST als Oststaaten TZ Akronym verwendet, aber EST und WST bleiben im allgemeinen Gebrauch).

Verwirrend viel?

Wenn alles, was Sie speichern müssen, ist ein UTC-Offset dann ein interval ist geeignet. Wenn Sie eine Zeitzone speichern möchten, speichern Sie sie unter text. Es ist ein Schmerz zu validieren und in eine Zeitzone zu versetzen, die im Moment ausgeglichen wird, aber zumindest bewältigt es DST.

+1

Gibt es einen Link zu den kanonischen Textstrings (Australien/Sydney) für alle Zeitzonen? – odigity

+1

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

+0

Wenn Sie die Leistung + Platz sparen (und Portabilität/Flexibilität reduzieren möchten), würde tz Datenbank + enum gut sein –

1

vielleicht Intervall

 
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" und "-hh: mm" sind keine Zeitzonen, sie sind UTC-Offsets. Ein gutes Format, um diese zu speichern, ist eine vorzeichenbehaftete Ganzzahl mit dem Offset in Minuten. Sie können auch Dinge wie interval verwenden, aber das wird Ihnen nur helfen, wenn Sie Datumsberechnungen direkt in PostgreSQL, wie in einer Abfrage usw. machen wollen. Normalerweise tun Sie diese Berechnungen in einer anderen Sprache, und dann hängt es von dieser Sprache ab unterstützt die interval Typ gut und hat eine gute Datum/Uhrzeit-Bibliothek oder nicht. Aber die Umwandlung einer ganzen Zahl in eine Art von interval-ähnlichen Typ, wie Pythons timedelta sollte trivial sein, so würde ich persönlich nur speichern es als eine ganze Zahl.

Zeitzonen haben Namen, und obwohl es keine standardisierten Namen für die Zeitzonen gibt, gibt es in der Datenbank "tz" oder "zoneinfo" einen De-facto-Standard, und zwar Namen wie "Europe/Paris", "Americas/New_York "oder" US/Pacific ". Diese sollten als Strings gespeichert werden.

Windows verwendet völlig andere Namen wie "Romance time" (nicht fragen). Sie können sie ebenso wie Strings speichern, aber ich würde es vermeiden, diese Namen werden nicht außerhalb von Windows verwendet, und die Namen ergeben keinen Sinn.Außerdem verwenden übersetzte Versionen von Fenstern tendenziell übersetzte Namen für diese Zeitzonen, was sie noch schlimmer macht.

Abkürzungen wie "PDT" und "EST" sind nicht als Zeitzonennamen verwendbar, da sie nicht eindeutig sind. Es gibt vier (ich denke, oder war es fünf?) Verschiedene Zeitzonen, die alle "CST" genannt werden, also ist das nicht verwendbar.

Kurz: Speichern Sie den Namen für Zeitzonen als Zeichenfolge. Bei UTC-Offsets speichern Sie den Offset in Minuten als eine Ganzzahl mit Vorzeichen.

+0

Gibt es einen Link zum kanonischen Text Saiten (Australien/Sydney) für alle Zeitzonen? – odigity

+0

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

4

In einer idealen Welt könnten Sie einen Fremdschlüssel zu einer Reihe bekannter Zeitzonen haben. Sie können etwas ähnliches mit Ansichten und Domänen tun.

Diese wiki tip von David E. Wheleer schafft eine Domäne, die für ihre Gültigkeit als Zeitzone getestet:

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

Es ist nützlich, um eine Liste der bekannten Zeitzonen, in diesem Fall können Sie mit der Domain verzichtet werden könnten und Durchsetzung nur die Einschränkung in der eine Tabelle, die die bekannten Zeitzone Namen, die (aus der Sicht erhalten pg_timezone_names), die Notwendigkeit vermieden wird, die Domain zu belichten an anderer Stelle:

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; 

Dann können Sie Korrektheit durch forei erzwingen gn Schlüssel:

CREATE TABLE myTable (
... 
tzone TEXT REFERENCES tzone(tzone_name) 
); 
Verwandte Themen