tech_memo / ORACLE / Timezone / SummerTime_analyze


tech_memo/ORACLE/Timezone

概要

  • Oracleの以下のデータ型のそれぞれについて、SummerTime?を用いて検証する
    • TIMESTAMP
    • TIMESTAMP WITH TIME ZONE
    • TIMESTAMP WITH LOCAL TIME ZONE

Table定義

NameNull?Type
IDNOT NULLNUMBER
TSTAMPTIMESTAMP(6)
TSTAMP_WITH_TZONETIMESTAMP(6) WITH TIME ZONE
TSTAMP_WITH_LOCAL_TZONETIMESTAMP(6) WITH LOCAL TIME ZONE
TZONEVARCHAR2(32)

レコードの登録方法

  • summer_time_1.png
  • 上記1の時間以前〜4時間、1sec間隔で以下のSQLを実行する
    INSERT INTO time_tab VALUES(time_seq.nextval, systimestamp, systimestamp, systimestamp, :B1);

Sample

IDTSTAMPTSTAMP_WITH_TZONETSTAMP_WITH_LOCAL_TZONETZONE
102-NOV-14 12.30.35.291756 AM02-NOV-14 12.30.35.291756 AM -07:0002-NOV-14 12.30.35.291756 AMUS/Pacific
202-NOV-14 12.30.36.373570 AM02-NOV-14 12.30.36.373570 AM -07:0002-NOV-14 12.30.36.373570 AMUS/Pacific
302-NOV-14 12.30.37.453699 AM02-NOV-14 12.30.37.453699 AM -07:0002-NOV-14 12.30.37.453699 AMUS/Pacific
402-NOV-14 12.30.38.533366 AM02-NOV-14 12.30.38.533366 AM -07:0002-NOV-14 12.30.38.533366 AMUS/Pacific
502-NOV-14 12.30.39.609287 AM02-NOV-14 12.30.39.609287 AM -07:0002-NOV-14 12.30.39.609287 AMUS/Pacific

Graph

  • 上記テーブルのそれぞれの型に関して、タイムスタンプをエポックタイムに変換して、直前のレコードとの時間差をグラフにする

TIMESTAMP型

  • 夏から冬時間に戻るタイミングで、3600sec時間がマイナスになっている
    • summer_time_2.png

TIMESTAMP WITH TIME ZONE型

  • 常に1~2secの差分。特に問題ない。
    • summer_time_3.png

TIMESTAMP WITH LOCAL TIME ZONE型

  • 夏時間の1:00に3600secプラスになり、冬時間の1:00に3600secマイナスになる
    • summer_time_4.png

エポックタイムが3600sec増減した前後のレコード情報

  • エポックタイムには、以下のSQLで変換している
    select 24*60*60*(cast(sys_extract_utc(<TIMESTAMPカラム>) as date) - date '1970-01-01') from <TABLE_NAME>;

Session Timezone 夏

  • 冬時間戻るタイミングで、TIMESTAMP型とTIMESTAMP WITH LOCAL TIMEZONE型のエポックタイムが-3600になる
    IDTSTAMPEPOC_TSTAMPEPOC_TSTAMP_TZONEEPOC_TSTAMP_LOCAL_TZONEEPOC_TSTAMP-EPOC_TSTAMP_TZONE
    499002-NOV-14 01.59.57.662344 AM1414918798141491879814149223980
    499102-NOV-14 01.59.58.738262 AM1414918799141491879914149223990
    499202-NOV-14 01.59.59.817931 AM1414918800141491880014149224000
    499302-NOV-14 01.00.00.898099 AM141491520114149188011414918801-3600
    499402-NOV-14 01.00.01.974019 AM141491520214149188021414918802-3600
    499502-NOV-14 01.00.03.049936 AM141491520314149188031414918803-3600

Session Timezone 冬

  • 冬時間に戻った段階で、エポックタイムが-3600になり、正常に戻る
    IDTSTAMPEPOC_TSTAMPEPOC_TSTAMP_TZONEEPOC_TSTAMP_LOCAL_TZONEEPOC_TSTAMP-EPOC_TSTAMP_TZONE
    499002-NOV-14 01.59.57.662344 AM1414922398141491879814149223983600
    499102-NOV-14 01.59.58.738262 AM1414922399141491879914149223993600
    499202-NOV-14 01.59.59.817931 AM1414922400141491880014149224003600
    499302-NOV-14 01.00.00.898099 AM1414918801141491880114149188010
    499402-NOV-14 01.00.01.974019 AM1414918802141491880214149188020
    499502-NOV-14 01.00.03.049936 AM1414918803141491880314149188030

TIMESTAMP型で正確なエポックタイムが取得できない理由

  • Oracleドキュメント : http://docs.oracle.com/cd/E16338_01/appdev.112/b61343/pc_04dat.htm
  • TIMESTAMP型のデータ格納形式が見つからなかったが、DATE型のデータ格納形式は以下のOracleドキュメントに説明がある。
    DATEデータ型を使用して、日付と時刻を7バイトの固定長フィールドに格納します。
    表4-3のように、世紀、年、月、日、時刻(24時間形式)、分、秒が、この順番で左から右に格納されています。
    • 表4-3 DATE書式
      DATEデータ型世紀
      バイト1234567
  • ドキュメントのTIMESTAMP型の説明
    TIMESTAMPデータ型は、DATEデータ型が拡張されたものです。DATEデータ型の年、月、日に加えて時、分および秒の値が格納されます。
    タイムゾーンはありません。
    • DATE型と同じく、年・月・日・時・分・秒の値でデータを格納している。TIMESTAMP型は絶対値となる値を格納していないと思われる。
  • つまり、TIMESTAMP型からエポックタイムを取得する際には、タイムゾーン情報が必要となる。
  • 夏時間終了時に2回発生する01:00~01:59の間にINSERTしたTIMESTAMP型の値は、SELECTする際には、SESSION_TIMEZONEが使用される。
  • 故に、夏時間にINSERTしたときのデータを、冬時間のセッションでSELECTすると、エポックタイムは3600secずれる。

タイム・ゾーン・データ型

データ型タイム・ゾーン小数秒
DATEなしなし
TIMESTAMPなしあり
TIMESTAMP WITH TIME ZONE明示的あり
TIMESTAMP WITH LOCAL TIME ZONE関連あり