sql >> Base de Datos >  >> RDS >> PostgreSQL

Manejar correctamente el TIEMPO CON ZONA HORARIA en PostgreSQL

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: