Haskell で日付計算 (CalendarTime)

old-time-1.0.0.4: Time library

> :m + System.Time
> t <- getClockTime
> t
Wed May  5 11:55:18 東京 (標準時) 2010
> :t t
t :: ClockTime

> :i ClockTime
data ClockTime = TOD Integer Integer 	-- Defined in System.Time
instance Eq ClockTime -- Defined in System.Time
instance Ord ClockTime -- Defined in System.Time
instance Show ClockTime -- Defined in System.Time

> TOD 0 0
Thu Jan  1 09:00:00 東京 (標準時) 1970
Prelude System.Time> TOD 1234567890 0
Sat Feb 14 08:31:30 東京 (標準時) 2009

日付時間は 1970/01/01 からの秒数として保持されるので、CalendarTime を作ってから ClockTime へ変換する。

>  let may05 = toClockTime $ CalendarTime 2010 May 5 0 0 0 0 Wednesday 0 "UTC" 0 False
> may05
Wed May  5 09:00:00 東京 (標準時) 2010

> let june04 = toClockTime $ CalendarTime 2010 June 4 0 0 0 0 Wednesday 0 "UTC" 0 False
> june04
Fri Jun  4 09:00:00 東京 (標準時) 2010  -- Wednesday で入力されても、toClockTimeが正しく修正。

Eq、Ord、のインスタンスがあるので比較が出来る。

> june04 > may05  --=> True
> let may05b = toClockTime $ CalendarTime 2010 May 5 0 0 0 0 Wednesday 0 "UTC" 0 False
> may05==may05b   --=> True
> may05==june04   --=> False

時間の加算。

>  addToClockTime (TimeDiff 10 0 0 0 0 0 0) may05 -- 10年後
Tue May  5 09:00:00 東京 (標準時) 2020

>  addToClockTime (TimeDiff 0 3 0 0 0 0 0) may05  -- 3ヶ月後
Thu Aug  5 09:00:00 東京 (標準時) 2010

>  addToClockTime (TimeDiff 0 0 20 0 0 0 0) may05  -- 20日後
Tue May 25 09:00:00  東京 (標準時) 2010

時間の差。

-- 5月5日から6月4日を引く
> diffClockTimes may05 june04  -- diffClockTimes は差の秒数を出力
TimeDiff {tdYear = 0, tdMonth = 0, tdDay = 0, tdHour = 0, tdMin = 0, tdSec = -2592000, tdPicosec = 0}

> diffClockTimes june04 may05  -- 6月4日から5月5日を引く
TimeDiff {tdYear = 0, tdMonth = 0, tdDay = 0, tdHour = 0, tdMin = 0, tdSec = 2592000, tdPicosec = 0}
-- 結果を文字列に変換
> timeDiffToString $ diffClockTimes may05 june04
"-2592000 secs"

-- normalizeTimeDiff 関数はTimeDiffを秒だけの値から年、月、日、時、分へ。
-- お金の両替で札、硬貨を最小にするようなイメージ。
> normalizeTimeDiff $ diffClockTimes may05 june04
TimeDiff {tdYear = 0, tdMonth = -1, tdDay = 0, tdHour = 0, tdMin = 0, tdSec = 0, tdPicosec = 0}

> normalizeTimeDiff $ diffClockTimes june04 may05
TimeDiff {tdYear = 0, tdMonth = 1, tdDay = 0, tdHour = 0, tdMin = 0, tdSec = 0, tdPicosec = 0}

> diffClockTimes june04 may05
TimeDiff {tdYear = 0, tdMonth = 0, tdDay = 0, tdHour = 0, tdMin = 0, tdSec = 2592000, tdPicosec = 0}

>   timeDiffToString $ normalizeTimeDiff $ diffClockTimes june04 may05
"1 month"

ctMonth の Month型、ctWDay の Day型は fromEnum で Int に変換できる。

ghci> getClockTime >>= toCalendarTime
CalendarTime {ctYear = 2011, ctMonth = April, ctDay = 13, 
 ctHour = 17, ctMin = 12, ctSec = 55, ctPicosec = 480158000000, 
 ctWDay = Wednesday, ctYDay = 102, ctTZName = "JST", ctTZ = 32400,
 ctIsDST = False}

> do{ ct<-getClockTime >>= toCalendarTime; 
      return (ctYear ct ,fromEnum (ctMonth ct) ,ctDay ct)}
 -- => (2011,3,13)

> getClockTime >>= toCalendarTime>>= (\ct->return (ctYear ct ,fromEnum (ctMonth ct) ,ctDay ct))

 -- => (2011,3,13)

> getClockTime >>= toCalendarTime >>= (return.fromEnum.ctMonth)
 -- => 3