如果你有一個普通的日期或時間戳沒有嵌入時區信息,你可以告訴Oracle把它當作一個特定的時間段是the from_tz()
function。然後,您可以使用會話時區作爲「本地」或具有特定命名時區的值(現在具有數據類型「區域時間戳」而不是簡單的「時間戳」)將該值轉換爲另一個帶有at time zone
datetime expression syntax的區域:
alter session set nls_date_format='YYYY-MM-DD HH24:MI:SS';
alter session set nls_timestamp_format='YYYY-MM-DD HH24:MI:SS';
alter session set nls_timestamp_tz_format='YYYY-MM-DD HH24:MI:SS TZR';
alter session set time_zone = 'America/New_York';
with cte (ts) as (
select timestamp '2017-02-08 12:00:00' from dual
)
select ts,
from_tz(ts, 'UTC') as ts_utc,
from_tz(ts, 'UTC') at local as ts_local,
from_tz(ts, 'UTC') at time zone 'Europe/Athens' as ts_athens
from cte;
TS TS_UTC TS_LOCAL TS_ATHENS
------------------- ----------------------- ------------------------------------ ---------------------------------
2017-02-08 12:00:00 2017-02-08 12:00:00 UTC 2017-02-08 07:00:00 AMERICA/NEW_YORK 2017-02-08 14:00:00 EUROPE/ATHENS
如果你從一個日起,那麼你必須調用from_tz()
之前將其轉換爲一個時間戳:
with cte (dt) as (
select cast(timestamp '2017-02-08 12:00:00' as date) from dual
)
select dt,
from_tz(cast(dt as timestamp), 'UTC') as ts_utc,
from_tz(cast(dt as timestamp), 'UTC') at local as ts_local,
from_tz(cast(dt as timestamp), 'UTC') at time zone 'Europe/Athens' as ts_athens
from cte;
DT TS_UTC TS_LOCAL TS_ATHENS
------------------- ----------------------- ------------------------------------ ---------------------------------
2017-02-08 12:00:00 2017-02-08 12:00:00 UTC 2017-02-08 07:00:00 AMERICA/NEW_YORK 2017-02-08 14:00:00 EUROPE/ATHENS
所以你原來date_1
值問題的數據類型一樣,在它應該表示的名義時區。如果它是一個;準備好'帶時區的時間戳'或'具有本地時區的時間戳',那麼它已經嵌入了時區信息,因此根本不需要from_tz()
部分。如果這是一個日期,您需要將其轉換爲時間戳。
假設date_1
存儲爲一個普通的時間戳(也許您的間隔增加暗示,而不是由你使用的列名和過濾器),它是名義上UTC,你可以這樣做:
from_tz(date_1, 'UTC') at time zone 'Europe/Athens'
。 ..這將給你一個'時區與時區'的結果;或者您可以使用local
來依賴您的會話時區。如果`DATE_1存儲爲一個日期,你要補充的轉換時間戳記:
from_tz(cast(date_1 as timestamp), 'UTC') at time zone 'Europe/Athens'
作爲演示,產生的CTE時間戳(不是日期),包括周圍的一些變化DST今年:
with tbl_1(date_1) as (
select timestamp '2017-02-08 10:00:00' from dual
union all select timestamp '2017-02-08 11:00:00' from dual
union all select timestamp '2017-02-08 12:00:00' from dual
union all select timestamp '2017-03-23 12:00:00' + numtodsinterval(level, 'day')
from dual connect by level <= 4
)
select date_1,
-- cast(from_tz(date_1, 'UTC') at time zone 'Europe/Athens' as timestamp) as date_2
to_char(from_tz(date_1, 'UTC') at time zone 'Europe/Athens',
'DD.MM.YYYY HH24:MI') as date_2
from tbl_1
order by date_1;
DATE_1 DATE_2
------------------- ----------------
2017-02-08 10:00:00 08.02.2017 12:00
2017-02-08 11:00:00 08.02.2017 13:00
2017-02-08 12:00:00 08.02.2017 14:00
2017-03-24 12:00:00 24.03.2017 14:00
2017-03-25 12:00:00 25.03.2017 14:00
2017-03-26 12:00:00 26.03.2017 15:00
2017-03-27 12:00:00 27.03.2017 15:00
您可以看到,3月26日時鐘更改後會自動添加額外的小時。但是對於二月份的樣本數據,結果已經過去了一個小時 - 所以您的數據實際上沒有存儲爲UTC(但是是-01:00,並且您可以更改from_tz()
調用以反映這一點),或者您的預期結果是錯誤。
爲什麼選擇postgresql標籤?你不使用Oracle嗎? – jarlh
「date_1」列的數據類型是什麼,它包含的值名義上包含哪些時區? –
@Alex Poole'date_1'的類型是'DATE',時區是'歐洲/雅典' – BOB