Data.DateTime を使ってみる

Data.DateTime : Utilities to make Data.Time.* easier to use.
CalendarTimeは計算は分り易いけれどSQL文字列への変換がやりにくい。
Data.DateTime というのがあったので使ってみる。

-- インストール
~$ cabal update
~$ cabal install datetime

fromClockTime で ClockTime 型から DateTime 型へ変換。

> :m + System.Time
-- ClockTime はエポックタイムからの秒とピコ秒
> :i TOD
data ClockTime = TOD Integer Integer 	-- Defined in System.Time

> TOD 0 0
Thu Jan  1 09:00:00 JST 1970

-- 1970/01/01 09:00:00より以前は負の数で表現。
> TOD (-1000000000) 0
Mon Apr 25 07:13:20 JST 1938

> getClockTime >>= (\(TOD sec pico) -> return (sec,pico))
(1297194216,84800000000)

> ctime<-getClockTime       -- System.Time
> ctime                     --=> Wed May  5 14:02:03 東京 (標準時) 2010
> let dateTime = fromClockTime ctime
> dateTime                  --=> 2010-05-05 05:02:03 UTC
> :t dateTime               --=> dateTime :: DateTime

文字列からDateTime型へ変換。

> let sqlStr = toSqlString dateTime
> sqlStr                    --=> "2010-05-05 05:02:03"
> fromSqlString  sqlStr     --=> Just 2010-05-05 05:02:03 UTC

DateTime型からタプルへ変換。

> toGregorian  dateTime     --=> (2010,5,5,5,2,3)
> :t toGregorian  dateTime
--=> toGregorian  dateTime :: (Integer, Int, Int, Int, Int, Int)
> toGregorian' dateTime     --=> (2010,5,5)
> :t toGregorian'  dateTime
--=> toGregorian' dateTime :: (Integer, Int, Int)

DateTime型から文字列へ変換。

> dt<-getCurrentTime        -- DateTime型でシステムから日時を取得
> dt                        --=> 2010-05-05 05:13:40.04951 UTC
> toSqlString dt            --=> "2010-05-05 05:13:40"
> :t toSqlString dt         --=>  toSqlString dt :: String

文字列からDateTime型へ変換するとJustとNothing のMaybe型になる。

> let new1= fromSqlString "2010-09-15 00:00:00"
> new1                     --=> Just 2010-09-15 00:00:00 UTC

> diffSeconds new1 dt      -- そのまま計算できない。

<interactive>:1:12:
    Couldn't match expected type `DateTime'
           against inferred type `Maybe DateTime'
    In the first argument of `diffSeconds', namely `new1'
    In the expression: diffSeconds new1 dt
    In the definition of `it': it = diffSeconds new1 dt

> let delJust (Just tm)=tm  -- Just を取り除く関数を作って
                            ーー DateTime型へ変換する
> delJust (new1)            --=> 2010-09-15 00:00:00 UTC

> let sec = diffSeconds (delJust new1) dt
> sec                    --=> 11472380
> :t sec                 --=> sec :: Integer
> addSeconds sec dt      --=> 2010-09-15 00:00:00 UTC

toGregorian の結果はタプル要素が数字なので、取り出した値も使いやすい。

> let grego = toGregorian  dt
> grego                  --=> (2010,5,5,5,13,40)
> :t grego               --=> grego :: (Integer, Int, Int, Int, Int, Int)

> let (year, month, day, _, _, _) = grego
> year                   --=> 2010
> month                  --=> 5
> day                    --=> 5

数字から DateTime 型を作るのは簡単。

> let g = fromGregorian'  2010 5 5
> g                      --=> 2010-05-05 00:00:00 UTC