Usted afirmó que:
Así que nunca cruce la línea de fecha dentro de la misma fila. Sugiero guardar 1x date
3x time
y la zona horaria (como text
o columna 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 ya encontraste, timetz
(time with time zone
) por lo general debe evitarse
. No puede manejar las reglas de horario de verano correctamente (d aylight s ahorro t momento).
Así que básicamente lo que ya tenías . Simplemente suelte el componente de fecha de start_hour
, eso es carga muerta. Enviar timestamp
a time
para cortar la fecha. Me gusta:(timestamp '2018-03-25 1:00:00')::time
tz
puede ser cualquier cadena aceptada por AT TIME ZONE
construcción, pero para tratar con diferentes zonas horarias de manera confiable, es mejor usar nombres de zona horaria exclusivamente. Cualquier name
encuentra en el catálogo del sistema pg_timezone_names
.
Para optimizar el almacenamiento, puede recopilar nombres de zonas horarias permitidas en una pequeña tabla de búsqueda y reemplazar tz text
con tz_id int REFERENCES my_tz_table
.
Dos filas de ejemplo con y sin 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 fines de representación o cálculos, puede hacer cosas 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;
Puede crear una o más vistas para mostrar cadenas fácilmente según sea necesario. La tabla es para almacenar la información que necesita .
¡Observe los paréntesis! De lo contrario, el operador +
enlazaría antes de AT TIME ZONE
debido a precedencia de operadores
.
Y he aquí los resultados:
db<>fiddle aquí
Dado que la hora se manipula en Viena (como en cualquier otro lugar donde se aplican reglas tontas de horario de verano), obtienes resultados "sorprendentes".
Relacionado:
- Contabilización del horario de verano en Postgres, al seleccionar elementos programados
- Ignorar el tiempo zonas por completo en Rails y PostgreSQL