2018年3月14日 星期三

日期運算概念

以鮮奶的「生產日期」及其「可保存天數」(假設為14天)為例,「生產日期」為日期資料,「可保存天數」為數值資料,單位為「天」,一般的想法是直接將「生產日期」加上「可保存天數」(假設為14天)即可得到「保存期限」。

對於日期型態資料,資料庫支援直接於日期加減(±)天數,即可將時間日期延後或提前(新的日期/時間);同理,如將兩個日期相減則可到差異天數,此為日期運算基本概念。
圖示 (2018-01-01 00:00為例)
說明






[
原日期 + 天數 = 新日期] [新日期 原日期=天數] ?
(1) 1.5
2018-01-02 12:00

(2) 2018-01-02 12:001.5
2018-01-01 00:00 ?


(1). 日期延後或提前(日期 ± 天數 =>目標時間.日期)
數值是直接以「」為單位,應用加(+)與減(-)運算符號進行日期加減運算(d1 ± = d2),如需提前/延後小時,則除以24轉換為「」,分鐘按其概念轉換亦同。操作如下

日期延後或提前
說明
MSSQL
SELECT d1
    , d1 + 1.5          "d2(d1+1.5)"
    , d1 + 1+ 12/24    "d2(d1+12/24)"
FROM
  (
  SELECT CAST('2018-01-01' AS datetime) d1
  ) A

d1
d2(d1 + 1.5)
d2(d1 + 12/24)
2018-01-01 00:00
2018-01-02 12:00
2018-01-02 00:00
請注意數學運算特性。12/24結果為0,非0.5

日期相減(差異)結果為日期型態,系統轉換相對1900-01-01起算之日期/時間。
ORACLE
SELECT d1
    , d1 + 1.5        "d2(d1+1.5)"
    , d1 + 1+ 12/24  "d2(d1+12/24)"
FROM
    (
    SELECT DATE'2018-01-01' d1
    FROM DUAL
    );

d1
d2(d1 + 1.5)
d2(d1 + 12/24)
2018-01-01 00:00
2018-01-02 12:00
2018-01-02 12:00

由於MSSQL數值運算概念稍特殊,使用上請謹慎以對,建議可先參考閱讀《MSSQL數學運算應注意事項》文章所述,以免誤判


(2). 日期、時間差(日期 - 日期 => 天數)
兩個日期的差距,則可採用日期減去另一個日期(d2-d1),MSSQLORACLE均適用,但兩者回傳結果為不同資料型態的,ORACLE為數值型態。

日期、時間差(日期-日期)
說明
MSSQL
SELECT
    d2 - d1           "diff = d2 - d1"
    , d1 + (d2 - d1)  "d2 = d1+(d2 - d1)"
    , d1 + Val        "d2 = d1 + 1.5"
  --, d1 + CAST(1.5 AS DATETIME) "d1+d"
FROM
  (
  SELECT CAST('2018-01-01' AS datetime)        d1
    , CAST('2018-01-02 12:00:00'AS datetime)   d2
    , 1.5 Val
  ) A;
diff=d2-d1
d2=d1+(d2-d1)
d2=d1+1.5
1900-01-02 12:00
2018-01-02 12:00
2018-01-02 12:00
時間-時間 = 時間
時間+時間 = 時間

ORACLE
SELECT
    d2 - d1           "diff = d2 - d1"
    , d1 + (d2 - d1)  "d2 = d1+(d2 - d1)"
    , d1 + Val        "d2 = d1 + 1.5"
FROM
  (
  SELECT DATE'2018-01-01'      d1
     , DATE'2018-01-02' +12/24 d2
     , 1.5 Val
  FROM DUAL
  )
diff=d2-d1
d2=d1+(d2-d1)
d2=d1+1.5
1.5
2018-01-02 12:00
2018-01-02 12:00
時間-時間 = 數值
時間+時間 è錯誤


測試結果整理如下表





ORACLE
MSSQL
日期延後或提前
日期 ± 數值()
日期型態
日期型態 


日期 + 日期()


支援ORA-00975錯誤
不支援日期 + 日期)
日期型態 
日期、時間差


日期 - 日期()
數值型態
差異轉為天,轉換為小時、分鐘
日期型態
差異轉換自1900-01-01起算之日期/時間


資料型態(Datatype)為欄位或預儲程序內變數的其中一個屬性(Attribute),描述並限制存放在欄位中資訊的種類,對於資料型態的選擇,最簡單準則就是『原本資料是什麼型態,就選擇什麼型態儲存』。
常見許多案例是將日期資料以字串或數值方式儲存(20181225),則已無法直接使用資料庫日期運算功能及函數等。

如本文可將日期延後或提前(日期±天數值)直接以「日」為單位應用加(+)與減(-)運算符號進行日期加減運算(d1 ± = d2),許多金融商品報價最後報價時間為17:0017:00前為當日,超過17:00後則視為次日,則可將時間遞移7小時(17+7 = 24)即可,此可大幅減化相關處理/運算複雜度。

此也常應用於半導體生產之四二輪報表,以07:30為換班時點並據以切分日期,07:30前為昨日,07:30後則為當日,如以CPMeas_Time為例,Meas_Time-7.5/24移動時間軸即為所求。

沒有留言:

張貼留言