sql >> Databáze >  >> RDS >> PostgreSQL

Správně zacházet s ČASEM S ČASOVÝM PÁSEM v PostgreSQL

Tvrdil jste, že:

Takže nikdy překročit datovou čáru ve stejném řádku. Navrhuji uložit 1x date 3x time a časové pásmo (jako text nebo sloupec FK):

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

Jak jste již našli, timetz (time with time zone ) je třeba se obecně vyhnout . Neumí správně pracovat s pravidly DST (d aylight s aving t ime).

Takže v podstatě to, co jste již měli . Stačí vypustit komponentu data z start_hour , to je mrtvý náklad. Odesílat timestamp na time přerušit datum. Líbí se:(timestamp '2018-03-25 1:00:00')::time

tz může být jakýkoli řetězec akceptovaný AT TIME ZONE ale pro spolehlivé řešení různých časových pásem je nejlepší používat výhradně názvy časových pásem. Jakékoli name najdete v systémovém katalogu pg_timezone_names .

Chcete-li optimalizovat úložiště, můžete shromáždit povolené názvy časových pásem v malé vyhledávací tabulce a nahradit tz text s tz_id int REFERENCES my_tz_table .

Dva příklady řádků s a bez 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

Pro reprezentační účely nebo výpočty můžete dělat věci jako:

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;

Můžete vytvořit jeden nebo více zobrazení pro snadné zobrazení řetězců podle potřeby. Tabulka slouží k uložení informací, které potřebujete .

Všimněte si závorek! Jinak operátor + se naváže před AT TIME ZONE kvůli přednosti provozovatele .

A podívejte se na výsledky:

db<>fiddle zde

Vzhledem k tomu, že se ve Vídni manipuluje s časem (jako kdekoli jinde, kde platí hloupá pravidla DST), získáte „překvapivé“ výsledky.

Související:




  1. zkopírujte tabulky s daty do jiné databáze v SQL Server 2008

  2. Jak spojit dvě tabulky na základě hodnot podřetězců polí?

  3. Převést datum na milisekundy v MySQL

  4. Práce s velkými daty JSON vrácenými webovým rozhraním API