TIMESTAMP WITH LOCAL TIME ZONE
działa tak:Kiedy musisz pracować ze strefami czasowymi w swojej aplikacji, powszechnym podejściem jest
Dokładnie tak TIMESTAMP WITH LOCAL TIME ZONE
działa - jedyna różnica to
Z tego powodu nie możesz zmienić DBTIMEZONE
(z ALTER DATABASE SET TIME_ZONE='...';
) w Twojej bazie danych, jeśli baza danych zawiera tabelę z TIMESTAMP WITH LOCAL TIME ZONE
kolumna i kolumna zawiera dane.
SYSTIMESTAMP
jest zwracany w strefie czasowej systemu operacyjnego serwera bazy danych. DBTIMEZONE
jest nie strefa czasowa SYSTIMESTAMP
lub SYSDATE
.
DBTIMEZONE
definiuje wewnętrzny format przechowywania TIMESTAMP WITH LOCAL TIME ZONE
kolumny typu danych. Zapomnij o tym, nie wyobrażam sobie żadnego przypadku użycia, w którym byłoby to potrzebne.
Właściwie Twoja tabela jest odpowiednikiem tego wyboru:
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;
Kiedy wykonujesz CAST({time without time zone} with local time zone)
następnie próbujesz przekonwertować wartość daty/godziny bez informacji o strefie czasowej na wartość daty/godziny ze strefą czasową. W zasadzie nie jest to możliwe, ponieważ Oracle nie ma informacji o strefie czasowej, więc Oracle zakłada strefę czasową. Jeśli wykonasz takie rzutowanie, Oracle zawsze uważa {czas bez strefy czasowej} jak podano w SESSIONTIMEZONE
(w momencie konwersji).
Więc CAST(sysdate AS timestamp(0) with local time zone)
jest odpowiednikiem
CAST(FROM_TZ(TO_TIMESTAMP(SYSDATE), SESSIONTIMEZONE) AS TIMESTAMP(0) WITH LOCAL TIME ZONE)`
ew. CAST(timestamp '2017-03-15 19:02:00' AS timestamp(0) with local time zone)
oznacza
CAST(FROM_TZ(TIMESTAMP '2017-03-15 19:02:00', SESSIONTIMEZONE) AS TIMESTAMP(0) WITH LOCAL TIME ZONE)
Dla SYSDATE
jest to właściwie błędne, ponieważ SYSDATE
jest podany w strefie czasowej systemu operacyjnego serwera bazy danych, a nie w SESSIONTIMEZONE. W przypadku drugiego zależy to od twojej intencji, czy wynik jest poprawny, czy nie.
SYSTIMESTAMP
zwraca wartość TIMESTAMP WITH TIME ZONE
, jest zawsze niezależny od aktualnego SESSIONTIMEZONE
. Ale jeśli przekonwertujesz na TIMESTAMP WITH LOCAL TIME ZONE
oczywiście zostanie przekonwertowany na aktualną lokalną strefę czasową. Możesz też użyć CURRENT_TIMESTAMP
lub SYSTIMESTAMP AT LOCAL
który robi mniej więcej to samo.
Ten kod
wydaje się być niesłuszne. Wynik powinien być
-- 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
Różnice wyglądają tak, jak powinny, ale wartości bezwzględne wydają się być „sfałszowane” (lub istnieje prawdziwy problem z bazą danych).