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:
- Contabilizando o horário de verão no Postgres, ao selecionar itens agendados
- Ignorando o tempo zones completamente em Rails e PostgreSQL