2016-06-21 6 views
1

UNIXのタイムスタンプで日付を変換できます。しかし、私はUNIXのタイムスタンプを修正するためにデータベース内の履歴データを変換する際に問題に直面しています。データは日付形式で保存されるため、これらのデータに使用できるタイムゾーンはありません。過去の日付がcdtかcstかを判断する方法はありますか?日付型オラクルの履歴データを、夏時間を考慮したunixタイムスタンプに変換します。

現在、タイムスタンプの日付を変換する方法の1つを使用しています。格納されたオブジェクトは、それがCDTとしてSYSタイムゾーンを取り、CSTタイムゾーンのデータのために1時間の差を与えるであろうないタイムゾーンを持っていないのでhttp://jrfom.com/2015archive/2012/02/10/oracle-and-unix-timestamps-revisited/

:から撮影

create or replace function unix_time_from_date 
     (
     in_date in date 
     -- in_src_tz in varchar2 default 'America/Chicago' 
    ) 
    return integer 
    as 
    ut  integer  := 0; 
    tz  varchar2(8) := ''; 
    tz_date timestamp with time zone; 
    tz_stmt varchar2(255); 
    in_src_tz varchar2(255):='America/Chicago'; 
    begin 
tz_stmt := 'select systimestamp at time zone ''' || in_src_tz || ''' from dual'; 



    execute immediate tz_stmt into tz_date; 
    select 
     extract(timezone_abbr from tz_date) 
    into tz 
    from dual; 



    -- Get the Unix timestamp 
    select 
     (new_time(in_date, tz, 'GMT') - to_date('01-JAN-1970', 'DD-MM-YYYY')) * (86400) 
    into ut 
    from dual; 

    return ut; 
end unix_time_from_date; 

答えて

1

のタイムゾーン省略形を今日として抽出し、指定した日付に適用します。実際にすべての日付がそのゾーンにあると仮定します。それは時間の半分の正しい結果をもたらしますが、渡される値の半分に過ぎません(冬では夏の時間が間違っています;夏では冬の時間が間違っています)。省略名の代わりにリージョン名を使用した場合、それは実行されません。しかし、あなたはnew_time()を使うことはできません。ちょっとだけゾーンを認識するので、at time zoneを使わなければなりません。

DSTの境界を越えている(これはロンドンでは実行されますが、シカゴでも動作します)、シカゴを想定している場合の関数では、現在の関数があなたに与えるものを見ることができます:

with t (dt) as (
    select add_months(trunc(sysdate), -level) 
    from dual 
    connect by level <= 6 
) 
select dt dt, 
    unix_time_from_date(dt) unix_time_from_date 
from t 
order by dt; 

DT     UNIX_TIME_FROM_DATE 
------------------- ------------------- 
2015-12-21 00:00:00   1450674000 
2016-01-21 00:00:00   1453352400 
2016-02-21 00:00:00   1456030800 
2016-03-21 00:00:00   1458536400 
2016-04-21 00:00:00   1461214800 
2016-05-21 00:00:00   1463806800 

Oracleに、その日付が表すはずの領域を示すことができます。タイムスタンプに日付をキャストすると、それは基本的に同じままです。それをtomeゾーンでタイムスタンプにキャストすると、サーバーのタイムゾーンが仮定されます。 、まだサーバーのタイムゾーンに基づいてUTC相当を取得する別の方法として、

with t (dt) as (
    select add_months(trunc(sysdate), -level) 
    from dual 
    connect by level <= 6 
) 
select dt dt, 
    cast(dt as timestamp) ts, 
    cast(dt as timestamp with time zone) tstz, 
    cast(dt as timestamp with time zone) at time zone 'UTC' as utc, 
    86400 * (cast(cast(dt as timestamp with time zone) at time zone 'UTC' as date) 
    - date '1970-01-01') as epoch 
from t 
order by dt; 

DT     TS     TSTZ        UTC       EPOCH 
------------------- ------------------- --------------------------------- ----------------------- ----------- 
2015-12-21 00:00:00 2015-12-21 00:00:00 2015-12-21 00:00:00 Europe/London 2015-12-21 00:00:00 UTC 1450656000 
2016-01-21 00:00:00 2016-01-21 00:00:00 2016-01-21 00:00:00 Europe/London 2016-01-21 00:00:00 UTC 1453334400 
2016-02-21 00:00:00 2016-02-21 00:00:00 2016-02-21 00:00:00 Europe/London 2016-02-21 00:00:00 UTC 1456012800 
2016-03-21 00:00:00 2016-03-21 00:00:00 2016-03-21 00:00:00 Europe/London 2016-03-21 00:00:00 UTC 1458518400 
2016-04-21 00:00:00 2016-04-21 00:00:00 2016-04-21 00:00:00 Europe/London 2016-04-20 23:00:00 UTC 1461193200 
2016-05-21 00:00:00 2016-05-21 00:00:00 2016-05-21 00:00:00 Europe/London 2016-05-20 23:00:00 UTC 1463785200 

:あなたはその後、at time zoneでUTCにそれを変換し、エポック番号を取得することから、1970年1月1日を引くことができますあなたはsys_extract_utc()を使用することができます。

with t (dt) as (
    select add_months(trunc(sysdate), -level) 
    from dual 
    connect by level <= 6 
) 
select dt dt, 
    cast(dt as timestamp) ts, 
    cast(dt as timestamp with time zone) tstz, 
    sys_extract_utc(cast(dt as timestamp)) as utc, 
    86400 * (cast(sys_extract_utc(cast(dt as timestamp with time zone)) as date) 
    - date '1970-01-01') as epoch 
from t 
order by dt; 

それとも、サーバーのタイムゾーンを使用したいが、とにかく、このデモのために少しより有用である、代わりに1を指定しない場合:

with t (dt) as (
    select add_months(trunc(sysdate), -level) 
    from dual 
    connect by level <= 6 
) 
select dt dt, 
    cast(dt as timestamp) ts, 
    from_tz(cast(dt as timestamp), 'America/Chicago') tstz, 
    from_tz(cast(dt as timestamp), 'America/Chicago') at time zone 'UTC' as utc, 
    86400 * (cast(from_tz(cast(dt as timestamp), 'America/Chicago') at time zone 'UTC' as date) 
    - date '1970-01-01') as epoch 
from t 
order by dt; 

DT     TS     TSTZ        UTC       EPOCH 
------------------- ------------------- ----------------------------------- ----------------------- ----------- 
2015-12-21 00:00:00 2015-12-21 00:00:00 2015-12-21 00:00:00 America/Chicago 2015-12-21 06:00:00 UTC 1450677600 
2016-01-21 00:00:00 2016-01-21 00:00:00 2016-01-21 00:00:00 America/Chicago 2016-01-21 06:00:00 UTC 1453356000 
2016-02-21 00:00:00 2016-02-21 00:00:00 2016-02-21 00:00:00 America/Chicago 2016-02-21 06:00:00 UTC 1456034400 
2016-03-21 00:00:00 2016-03-21 00:00:00 2016-03-21 00:00:00 America/Chicago 2016-03-21 05:00:00 UTC 1458536400 
2016-04-21 00:00:00 2016-04-21 00:00:00 2016-04-21 00:00:00 America/Chicago 2016-04-21 05:00:00 UTC 1461214800 
2016-05-21 00:00:00 2016-05-21 00:00:00 2016-05-21 00:00:00 America/Chicago 2016-05-21 05:00:00 UTC 1463806800 

そして、あなたの機能とのエポックを計算することを比較する:

with t (dt) as (
    select add_months(trunc(sysdate), -level) 
    from dual 
    connect by level <= 6 
) 
select dt dt, 
    unix_time_from_date(dt) unix_time_from_date, 
    86400 * (cast(from_tz(cast(dt as timestamp), 'America/Chicago') at time zone 'UTC' as date) 
    - date '1970-01-01') as epoch, 
    unix_time_from_date(dt) - 
    ( 86400 * (cast(from_tz(cast(dt as timestamp), 'America/Chicago') at time zone 'UTC' as date) 
    - date '1970-01-01')) as diff 
from t 
order by dt; 

DT     UNIX_TIME_FROM_DATE  EPOCH DIFF 
------------------- ------------------- ----------- ------ 
2015-12-21 00:00:00   1450674000 1450677600 -3600 
2016-01-21 00:00:00   1453352400 1453356000 -3600 
2016-02-21 00:00:00   1456030800 1456034400 -3600 
2016-03-21 00:00:00   1458536400 1458536400  0 
2016-04-21 00:00:00   1461214800 1461214800  0 
2016-05-21 00:00:00   1463806800 1463806800  0 

しかし、あなたはまだ状態に持っている - ので、多分が前提と - 日付が最初に表さ何時間帯。あなたはすでにあなたの関数でそれをやっているので、私はそれが問題だとは思わない。

+0

ありがとうございます。質問を投稿する前にUTCでキャストできませんでした。あなたは問題を解決しました。 – sinner

関連する問題