TIMESTAMP WITH LOCAL TIME ZONE
funguje takto:Když musíte ve své aplikaci pracovat s časovými pásmy, pak běžný přístup je
Přesně tak TIMESTAMP WITH LOCAL TIME ZONE
funguje - jediný rozdíl je
Z tohoto důvodu nemůžete změnit DBTIMEZONE
(s ALTER DATABASE SET TIME_ZONE='...';
) již ve vaší databázi, pokud databáze obsahuje tabulku s TIMESTAMP WITH LOCAL TIME ZONE
a sloupec obsahuje data.
SYSTIMESTAMP
se vrací v časové zóně operačního systému databázového serveru. DBTIMEZONE
není časové pásmo SYSTIMESTAMP
nebo SYSDATE
.
DBTIMEZONE
definuje formát interního úložiště TIMESTAMP WITH LOCAL TIME ZONE
sloupce datových typů. Zapomeňte na to, neumím si představit žádný případ použití, kdy byste to potřebovali.
Vaše tabulka je ve skutečnosti ekvivalentní tomuto výběru:
select
CAST(systimestamp AS timestamp(0) with local time zone) as SYSTIMESTAMP_COL,
CAST(sysdate AS timestamp(0) with local time zone) as SYSDATE_COL,
CAST(current_timestamp AS timestamp(0) with local time zone) as CURRENT_TIMESTAMP_COL,
CAST(timestamp '2017-03-15 19:02:00' AS timestamp(0) with local time zone) as DATE_COL
from dual;
Když provedete CAST({time without time zone} with local time zone)
potom se pokusíte převést hodnotu data a času bez jakýchkoli informací o časovém pásmu na hodnotu data a času s časovým pásmem. V zásadě to není možné, protože Oracle postrádá informace o časovém pásmu, takže Oracle předpokládá časové pásmo. Pokud provedete takové obsazení, Oracle vždy vezme v úvahu {čas bez časového pásma}, jak je uvedeno v SESSIONTIMEZONE
(v okamžiku konverze).
Takže CAST(sysdate AS timestamp(0) with local time zone)
je ekvivalentní
CAST(FROM_TZ(TO_TIMESTAMP(SYSDATE), SESSIONTIMEZONE) AS TIMESTAMP(0) WITH LOCAL TIME ZONE)`
resp. CAST(timestamp '2017-03-15 19:02:00' AS timestamp(0) with local time zone)
znamená
CAST(FROM_TZ(TIMESTAMP '2017-03-15 19:02:00', SESSIONTIMEZONE) AS TIMESTAMP(0) WITH LOCAL TIME ZONE)
Pro SYSDATE
to je ve skutečnosti špatně, protože SYSDATE
je uveden v časové zóně operačního systému databázového serveru, nikoli v SESSIONTIMEZONE. U druhého záleží na vašem záměru, zda je výsledek správný nebo ne.
SYSTIMESTAMP
vrátí hodnotu TIMESTAMP WITH TIME ZONE
, je vždy nezávislý na vašem aktuálním SESSIONTIMEZONE
. Ale pokud převedete na TIMESTAMP WITH LOCAL TIME ZONE
převede se samozřejmě na vaše aktuální místní časové pásmo. Můžete také použít CURRENT_TIMESTAMP
nebo SYSTIMESTAMP AT LOCAL
který dělá víceméně totéž.
Tento kód
se zdá být špatně. Výsledek by měl být
-- SYSTIMESTAMP_COL 15/03/2017 16:01:14
-- SYSDATE_COL 15/03/2017 19:01:14
-- CURRENT_TIMESTAMP_COL 15/03/2017 16:01:14
-- DATE_COL 15/03/2017 19:02:00
Rozdíly vypadají tak, jak by měly být, ale absolutní hodnoty se zdají být "falešné" (nebo existuje skutečný problém s vaší databází).