PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Manipule adequadamente TIME WITH TIME ZONE no PostgreSQL


Você afirmou que:

Então você nunca cruzar a linha de data dentro da mesma linha. Sugiro salvar 1x date 3x time e o fuso horário (como text ou coluna 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
);

Como você já encontrou, timetz (time with time zone ) geralmente deve ser evitado . Ele não pode lidar com as regras de horário de verão adequadamente (d luz s salvando t eu).

Então basicamente o que você já tinha . Basta soltar o componente de data de start_hour , isso é frete morto. Transmitir timestamp para time para cortar a data. Como:(timestamp '2018-03-25 1:00:00')::time

tz pode ser qualquer string aceita pelo AT TIME ZONE construir, mas para lidar com diferentes fusos horários de forma confiável, é melhor usar nomes de fuso horário exclusivamente. Qualquer name você encontra no catálogo do sistema pg_timezone_names .

Para otimizar o armazenamento, você pode coletar os nomes de fuso horário permitidos em uma pequena tabela de pesquisa e substituir tz text com tz_id int REFERENCES my_tz_table .

Duas linhas de exemplo com e sem 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

Para fins de representação ou cálculos, você pode fazer coisas como:
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;

Você pode criar uma ou mais visualizações para exibir prontamente as strings conforme necessário. A tabela é para armazenar as informações que você precisa .

Observe os parênteses! Caso contrário, o operador + vincularia antes de AT TIME ZONE devido à precedência do operador .

E vejam os resultados:

db<>fiddle aqui

Como o horário é manipulado em Viena (como em qualquer lugar onde se aplicam regras tolas de horário de verão), você obtém resultados "surpreendentes".

Relacionado: