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

Reprezentowanie przyszłości w PostgreSQL

Wygląda na to, że chcesz zapisać czas lokalny w odniesieniu do określonej strefy czasowej. W takim przypadku zapisz timestamp (bez strefy czasowej) i timezone w osobnej kolumnie.

Załóżmy na przykład, że chcesz nagrać wydarzenie, które będzie miało miejsce o godzinie 10 rano 26 lutego 2030 roku w Chicago i musi mieć miejsce o godzinie 10 rano czasu lokalnego niezależnie od reguły strefy czasowej obowiązującej w tym dniu.

Jeśli baza danych przechowuje znacznik czasu bez strefy czasowej:

unutbu=# select '2030-02-26 10:00:00'::timestamp as localtime, 'America/Chicago' AS tzone;
+---------------------+-----------------+
|      localtime      |      tzone      |
+---------------------+-----------------+
| 2030-02-26 10:00:00 | America/Chicago |
+---------------------+-----------------+

Później możesz znaleźć datę i godzinę wydarzenia UTC za pomocą

unutbu=# select '2030-02-26 10:00:00'::timestamp AT TIME ZONE 'America/Chicago' AT TIME ZONE 'UTC';
+---------------------+
|      timezone       |
+---------------------+
| 2030-02-26 16:00:00 |
+---------------------+

Zapytanie zwraca datę i godzinę UTC, 2030-02-26 16:00:00 , co odpowiada 2030-02-26 10:00:00 czas lokalny w Chicago.

Korzystanie z AT TIME ZONE opóźnia zastosowanie reguł strefy czasowej do kiedy zapytanie jest wykonane zamiast kiedy timestamptz został wstawiony.

Korzystanie z AT TIME ZONE na timestamp lokalizuje datę i godzinę na podaną strefę czasową, ale raporty data i godzina w strefie czasowej użytkownika .Korzystanie z AT TIME ZONE na timestamp konwertuje datę i godzinę na podaną strefę czasową, a następnie usuwa przesunięcie, zwracając w ten sposób timestamp .Powyżej, AT TIME ZONE jest używany dwukrotnie:najpierw do lokalizacji timestamp a następnie przekonwertować zwrócony timestamp do nowej strefy czasowej (UTC). Wynikiem jest timestamp w UTC.

Oto przykład demonstrujący AT TIME ZONE zachowanie na timestamp s:

unutbu=# SET timezone = 'America/Chicago';
unutbu=# SELECT '2030-02-26 10:00:00'::timestamp AT TIME ZONE 'America/Chicago';
+------------------------+
|        timezone        |
+------------------------+
| 2030-02-26 10:00:00-06 |
+------------------------+

unutbu=# SET timezone = 'America/Los_Angeles';
unutbu=# SELECT '2030-02-26 10:00:00'::timestamp AT TIME ZONE 'America/Chicago';
+------------------------+
|        timezone        |
+------------------------+
| 2030-02-26 08:00:00-08 |
+------------------------+

2030-02-26 10:00:00-06 i 2030-02-26 08:00:00-08 to te same daty i godziny, ale zgłoszone w różnych strefach czasowych użytkownika. To pokazuje, że 10 rano w Chicago jest 8 rano w Los Angeles (przy użyciu aktualnych definicji stref czasowych):

unutbu=# SELECT '2030-02-26 10:00:00-06'::timestamptz AT TIME ZONE 'America/Los_Angeles';
+---------------------+
|      timezone       |
+---------------------+
| 2030-02-26 08:00:00 |
+---------------------+

Alternatywa dla używania AT TIME ZONE dwa razy to ustawienie strefy czasowej użytkownika do UTC . Wtedy możesz użyć

select localtime AT TIME ZONE tzone

Zauważ, że gdy zrobisz to w ten sposób, timestamp jest zwracany zamiast timestamp .

Pamiętaj, że przechowywanie czasów lokalnych może być problematyczne, ponieważ mogą istnieć nieistniejące czasy i niejednoznaczne czasy. Na przykład 2018-03-11 02:30:00 to nieistniejący czas lokalny w America/Chicago . Postgresql normalizuje nieistniejący czas lokalny, zakładając, że odnosi się on do odpowiedniego czasu po rozpoczęciu czasu letniego (DST) (jakby ktoś zapomniał przestawić swój zegar do przodu):

unutbu=# select '2018-03-11 02:30:00'::timestamp AT TIME ZONE 'America/Chicago' AT TIME ZONE 'UTC';
+---------------------+
|      timezone       |
+---------------------+
| 2018-03-11 08:30:00 |
+---------------------+
(1 row)

unutbu=# select '2018-03-11 03:30:00'::timestamp AT TIME ZONE 'America/Chicago' AT TIME ZONE 'UTC';
+---------------------+
|      timezone       |
+---------------------+
| 2018-03-11 08:30:00 |
+---------------------+
(1 row)

Przykładem niejednoznacznego czasu lokalnego jest 2018-11-04 01:00:00 w America/Chicago . Występuje dwukrotnie z powodu czasu letniego. Postgresql rozwiązuje tę niejednoznaczność, wybierając późniejszy czas, po zakończeniu czasu letniego:

unutbu=# select '2018-11-04 01:00:00'::timestamp AT TIME ZONE 'America/Chicago' AT TIME ZONE 'UTC';
+---------------------+
|      timezone       |
+---------------------+
| 2018-11-04 07:00:00 |
+---------------------+

Zauważ, że oznacza to, że nie ma możliwości odwołania się do 2018-11-04 06:00:00 UTC przechowując czasy lokalne w America/Chicago strefa czasowa:

unutbu=# select '2018-11-04 00:59:59'::timestamp AT TIME ZONE 'America/Chicago' AT TIME ZONE 'UTC';
+---------------------+
|      timezone       |
+---------------------+
| 2018-11-04 05:59:59 |
+---------------------+


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. 3 sposoby formatowania liczby jako wartości procentowej w PostgreSQL

  2. Jak uzyskać nazwę zmienionej tabeli w wyzwalaczu zdarzenia Postgres?

  3. Znajdź najdłuższą passę doskonałych wyników na gracza

  4. Uzyskaj krótką nazwę miesiąca w PostgreSQL

  5. C#, Entity Framework Core &PostgreSql :wstawienie pojedynczego wiersza zajmuje ponad 20 sekund