PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Prawidłowa obsługa TIME WITH TIME STREFA w PostgreSQL

Zapewniłeś, że:

Więc nigdy przekroczyć linię daty w tym samym wierszu. Proponuję zapisać 1x date 3x time i strefa czasowa (jako text lub kolumna 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 już znalazłeś, timetz (time with time zone ) należy generalnie unikać . Nie radzi sobie poprawnie z regułami czasu letniego (d aylight s świerz t ime).

Więc w zasadzie to, co już miałeś . Po prostu upuść komponent daty z start_hour , to martwy ładunek. Przesyłaj timestamp do time odciąć datę. Na przykład:(timestamp '2018-03-25 1:00:00')::time

tz może być dowolnym ciągiem zaakceptowanym przez AT TIME ZONE konstruować, ale aby niezawodnie radzić sobie z różnymi strefami czasowymi, najlepiej używać wyłącznie nazw stref czasowych. Dowolna name znajdziesz w katalogu systemowym pg_timezone_names .

Aby zoptymalizować pamięć, możesz zebrać dozwolone nazwy stref czasowych w małej tabeli wyszukiwania i zastąpić tz text z tz_id int REFERENCES my_tz_table .

Dwa przykładowe rzędy z i 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

Do celów reprezentacyjnych lub obliczeń możesz wykonać takie czynności, jak:

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;

Możesz utworzyć jeden lub więcej widoków aby łatwo wyświetlać ciągi w razie potrzeby. Tabela służy do przechowywania informacji, których potrzebujesz .

Zwróć uwagę na nawiasy! W przeciwnym razie operator + powiąże się przed AT TIME ZONE ze względu na pierwszeństwo operatorów .

I spójrz na wyniki:

db<>fiddle tutaj

Ponieważ czas jest manipulowany w Wiedniu (jak w każdym miejscu, w którym obowiązują głupie zasady czasu letniego), otrzymujesz „zaskakujące” wyniki.

Powiązane:




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Czy można wydać VACUUM ANALYZE <nazwa tabeli> z psycopg2 lub sqlalchemy dla PostgreSQL?

  2. PostgreSQL:Iteruj przez wiersze tabeli z pętlą for, pobieraj wartość kolumny na podstawie bieżącego wiersza

  3. Czy powinienem określić zarówno INDEX, jak i UNIQUE INDEX?

  4. WYBIERZ lub WSTAW wiersz w jednym poleceniu

  5. Jak używać RETURNING z ON CONFLICT w PostgreSQL?