sql >> Database >  >> RDS >> PostgreSQL

Op de juiste manier omgaan met TIME WITH TIME ZONE in PostgreSQL

U beweerde dat:

Dus je nooit kruis de een datumlijn binnen dezelfde rij. Ik stel voor om 1x date op te slaan 3x time en de tijdzone (als text of FK-kolom):

CREATE TABLE legacy_table (
   event_id      bigint PRIMARY KEY NOT NULL
 , report_date   date NOT NULL
 , start_hour    time
 , end_hour      time
 , expected_hour time
 , tz            text  -- time zone
);

Zoals je al hebt gevonden, timetz (time with time zone ) moet over het algemeen worden vermeden . Het kan niet goed omgaan met de zomertijdregels (d aylight s aving t tijd).

Dus in feite wat je al had . Laat de datumcomponent gewoon vallen uit start_hour , dat is dode vracht. Cast timestamp tot time om de datum af te snijden. Zoals:(timestamp '2018-03-25 1:00:00')::time

tz kan elke tekenreeks zijn die wordt geaccepteerd door de AT TIME ZONE constructie, maar om betrouwbaar met verschillende tijdzones om te gaan, kunt u het beste uitsluitend tijdzonenamen gebruiken. Elke name vindt u in de systeemcatalogus pg_timezone_names .

Om de opslag te optimaliseren, kunt u toegestane tijdzonenamen verzamelen in een kleine opzoektabel en tz text vervangen met tz_id int REFERENCES my_tz_table .

Twee voorbeeldrijen met en zonder DST:

INSERT INTO legacy_table VALUES
   (1, '2018-03-25', '1:00', '3:00', '2:00', 'Europe/Vienna')  -- sadly, with DST
 , (2, '2018-03-25', '1:00', '3:00', '2:00', 'Europe/Moscow'); -- Russians got rid of DST

Voor representatiedoeleinden of berekeningen kunt u dingen doen als:

SELECT (report_date + start_hour)    AT TIME ZONE tz AT TIME ZONE 'UTC' AS start_utc
     , (report_date + end_hour)      AT TIME ZONE tz AT TIME ZONE 'UTC' AS end_utc
     , (report_date + expected_hour) AT TIME ZONE tz AT TIME ZONE 'UTC' AS expected_utc
     -- START_HOUR - END_HOUR
     , (report_date + start_hour) AT TIME ZONE tz
     - (report_date + end_hour)   AT TIME ZONE tz AS start_minus_end
FROM   legacy_table;

U kunt een of meer weergaven maken om gemakkelijk strings weer te geven als dat nodig is. De tabel is voor het opslaan van de informatie die u nodig .

Let op de haakjes! Anders de operator + zou binden vóór AT TIME ZONE vanwege operatorvoorrang .

En ziedaar de resultaten:

db<>fiddle hier

Omdat de tijd in Wenen wordt gemanipuleerd (zoals overal waar gekke zomertijdregels gelden), krijg je "verrassende" resultaten.

Gerelateerd:




  1. Tabel wijzigen mislukt omdat een rij onjuiste gegevens bevat - Onjuiste datetime-waarde:'0000-00-00 00:00:00'

  2. Herstel MySQL DB met Unicode-tekens (Arabisch en Koerdisch) in .gz-indeling

  3. een aantal unieke waarden krijgen zonder waarden te scheiden die tot hetzelfde waardenblok behoren

  4. Welk kolomtype gebruikt SQLAlchemy voor tekst op MySQL?