Du påstod att:
Så du aldrig korsa en datumlinje inom samma rad. Jag föreslår att du sparar 1x date
3x time
och tidszonen (som text
eller FK-kolumnen):
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 redan hittat, timetz
(time with time zone
) bör i allmänhet undvikas
. Den kan inte hantera sommartidsreglerna ordentligt (d aylight s aving t ime).
Så i princip vad du redan hade . Släpp bara datumkomponenten från start_hour
, det är dödfrakt. Cast timestamp
till time
att klippa av datumet. Gilla:(timestamp '2018-03-25 1:00:00')::time
tz
kan vara vilken sträng som helst som accepteras av AT TIME ZONE
konstruera, men för att hantera olika tidszoner på ett tillförlitligt sätt är det bäst att uteslutande använda tidszonsnamn. Alla name
hittar du i systemkatalogen pg_timezone_names
.
För att optimera lagringen kan du samla tillåtna tidszonnamn i en liten uppslagstabell och ersätta tz text
med tz_id int REFERENCES my_tz_table
.
Två exempelrader med och utan sommartid:
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
För representationsändamål eller beräkningar kan du göra saker 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 skapa en eller flera vyer för att enkelt visa strängar vid behov. Tabellen är till för att lagra den information du behöver .
Notera parentesen! Annars operatorn +
skulle binda före AT TIME ZONE
på grund av operatörsföreträde
.
Och se resultatet:
db<>fiol här
Eftersom tiden är manipulerad i Wien (som alla platser där dumma sommarregler gäller) får du "överraskande" resultat.
Relaterat:
- Redovisning för sommartid i Postgres, när du väljer schemalagda objekt
- Ignorerar tid zoner helt och hållet i Rails och PostgreSQL