sql >> Database teknologi >  >> RDS >> PostgreSQL

Håndter TIME WITH TIME ZONE korrekt i PostgreSQL

Du hævdede, at:

Så du aldrig krydse a-datolinjen i samme række. Jeg foreslår at gemme 1x date 3x time og tidszonen (som text eller FK kolonne):

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

Som du allerede har fundet, timetz (time with time zone ) bør generelt undgås . Det kan ikke håndtere sommertidsregler korrekt (d aylight s aving t ime).

dybest set hvad du allerede havde . Bare slip datokomponenten fra start_hour , det er dødfragt. Cast timestamp til time at skære datoen af. Like:(timestamp '2018-03-25 1:00:00')::time

tz kan være en hvilken som helst streng, der accepteres af AT TIME ZONE konstruere, men for at håndtere forskellige tidszoner pålideligt, er det bedst udelukkende at bruge tidszonenavne. Ethvert name du finder i systemkataloget pg_timezone_names .

For at optimere lagringen kan du samle tilladte tidszonenavne i en lille opslagstabel og erstatte tz text med tz_id int REFERENCES my_tz_table .

To eksempler på rækker med og uden sommertid:

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

Til repræsentationsformål eller beregninger kan du gøre ting som:

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;

Du kan muligvis oprette en eller flere visninger for nemt at vise strenge efter behov. Tabellen er til lagring af de oplysninger, du bruger for .

Bemærk parentesen! Ellers operatoren + ville binde før AT TIME ZONE på grund af operatørprioritet .

Og se resultaterne:

db<>fiddle her

Da tiden er manipuleret i Wien (som alle steder, hvor dumme sommertidsregler gælder), får du "overraskende" resultater.

Relateret:




  1. meta_query, hvordan søger man ved at bruge både relation ELLER &OG?

  2. Kan ikke finde objektet, fordi det ikke eksisterer, eller du ikke har tilladelser. Fejl i SQL Server

  3. Omvendt koordinater i PostgreSQL polygon kolonne

  4. Hvordan opretter man indeks på JSON-feltet i Postgres?