少なくとも2005年ごろには認識されていることですが、一応メモ。これが理由か分かりませんが、現在ではこのモジュールに代わるData.Time
の利用が推奨されています。
問題点
System.Time
にはTimeDiff
という日付の差を表現するデータ型と、それを正規化するnormalizeTimeDiff :: TimeDiff -> TimeDiff
という関数があります。TimeDiff
の定義は次の通り。
data TimeDiff
= TimeDiff {
tdYear :: Int,
tdMonth :: Int,
tdDay :: Int,
tdHour :: Int,
tdMin :: Int,
tdSec :: Int,
tdPicosec :: Integer -- not standard
}
deriving (Eq,Ord,Read,Show)
TimeDiff
の正規化というのは、可能な限り上位の時間単位を使った表現へ変換することです。(例:13ヶ月→1年1ヶ月)
ここで思うのは**「TimeDiff
の正規化は無理筋なのでは・・・?」**ということ。月によって1ヶ月に含まれる日数が異なるからです。
というわけで試してみます。
Prelude> :m + System.Time
Prelude System.Time> let oct1 = toClockTime $ CalendarTime 2016 October 1 0 0 0 0 Saturday 0 "UTC" 0 False
Prelude System.Time> let nov1 = toClockTime $ CalendarTime 2016 November 1 0 0 0 0 Tuesday 0 "UTC" 0 False
Prelude System.Time> let d = nov1 `diffClockTimes` oct1
Prelude System.Time> d `addToClockTime` oct1
Tue Nov 1 09:00:00 JST 2016
Prelude System.Time> (normalizeTimeDiff d) `addToClockTime` oct1
Wed Nov 2 09:00:00 JST 2016
正規化したTimeDiff
を足してやると日付が一日ずれてしまいました。
normalizeTimeDiff
では1ヶ月を一律30日として計算しているためこのようなことが起こります。
Prelude System.Time> d
TimeDiff {tdYear = 0, tdMonth = 0, tdDay = 0, tdHour = 0, tdMin = 0, tdSec = 2678400, tdPicosec = 0}
Prelude System.Time> normalizeTimeDiff d
TimeDiff {tdYear = 0, tdMonth = 1, tdDay = 1, tdHour = 0, tdMin = 0, tdSec = 0, tdPicosec = 0}
ちなみに1年の方も一律に365日で計算されます。