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