sql >> Databáze >  >> RDS >> PostgreSQL

Reprezentující budoucí čas v PostgreSQL

Zdá se, že chcete uložit místní čas s ohledem na určité časové pásmo. V takovém případě uložte timestamp (bez časového pásma) a timezone v samostatném sloupci.

Předpokládejme například, že chcete zaznamenat událost, která se stane v 10:00 26. února 2030 v Chicagu a musí to být v 10:00 místního času bez ohledu na pravidlo časového pásma platné k danému datu.

Pokud databáze ukládá časové razítko bez časového pásma:

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 |
+---------------------+-----------------+

Později můžete najít UTC datum a čas události 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 |
+---------------------+

Dotaz vrátí datum a čas UTC, 2030-02-26 16:00:00 , což odpovídá 2030-02-26 10:00:00 místního času v Chicagu.

Pomocí AT TIME ZONE zpoždění použití pravidel časového pásma do kdy je dotaz proveden namísto kdy timestamptz byl vložen.

Pomocí AT TIME ZONE na timestamp lokalizuje datum a čas do daného časového pásma, ale nahlásí datum a čas v časovém pásmu uživatele .Pomocí AT TIME ZONE na timestamptz převede datum a čas na dané časové pásmo, poté posune posun, čímž vrátí timestamp .Nahoře AT TIME ZONE se používá dvakrát:nejprve k lokalizaci timestamp a vedle převést vrácené timestamptz do nového časového pásma (UTC). Výsledkem je timestamp v UTC.

Zde je příklad demonstrující AT TIME ZONE chování uživatele 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 a 2030-02-26 08:00:00-08 jsou stejné datum-časy, ale jsou hlášeny v různých časových pásmech uživatelů. Toto ukazuje, že 10:00 v Chicagu je 8:00 v Los Angeles (s použitím aktuálních definic časového pásma):

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

Alternativa k použití AT TIME ZONE dvakrát je nastavit časové pásmo uživatele do UTC . Pak můžete použít

select localtime AT TIME ZONE tzone

Všimněte si, že když to uděláte tímto způsobem, timestamptz je vráceno místo timestamp .

Mějte na paměti, že ukládání místních časů může být problematické, protože mohou existovat neexistující časy a nejednoznačné časy. Například 2018-03-11 02:30:00 je neexistující místní čas v America/Chicago . Postgresql normalizuje neexistující místní časy za předpokladu, že odkazuje na odpovídající čas po začátku letního času (DST) (jako by někdo zapomněl nastavit hodiny dopředu):

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)

Příklad nejednoznačného místního času je 2018-11-04 01:00:00 v America/Chicago . Vyskytuje se dvakrát kvůli DST. Postgresql řeší tuto nejednoznačnost výběrem pozdějšího času po skončení DST:

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 |
+---------------------+

Všimněte si, že to znamená, že neexistuje způsob, jak odkazovat na 2018-11-04 06:00:00 UTC uložením místních časů v America/Chicago časové pásmo:

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. ORA-00942:Lze vybrat ze schema.table, ale ne z tabulky?

  2. Připojte se k Oracle bez tnsname.ora

  3. snadné způsoby výběru řádků ze všech tabulek

  4. Jak používat klauzuli GROUP BY v SQL