西暦から和暦に変換

type Year  = Integer
type Month = Int
type Day   = Int

data Nengo  = Nengo { start::(Year, Month, Day), end::(Year, Month, Day), name::String} deriving (Eq,Show)

nengoTable :: [Nengo]
nengoTable = [
    Nengo { start = (1868, 1,25), end = (1912, 7,29), name = "Meiji"},
    Nengo { start = (1912, 7,30), end = (1926,12,24), name = "Taisho"}, 
    Nengo { start = (1926,12,25), end = (1989, 1, 7), name = "Showa"}, 
    Nengo { start = (1989, 1, 8), end = (2100,12,31), name = "Heisei"}]  

toWareki :: (Year, Month, Day) -> Maybe (String, (Year, Month, Day))
toWareki = toWareki' nengoTable

toWareki' :: [Nengo] -> (Year, Month, Day) -> Maybe (String, (Year, Month, Day))
toWareki' []     date = Nothing
toWareki' (x:xs) date = 
    if isBetween date x then Just (name x, (nengo, month date, day date))
                        else toWareki' xs date 
      where
        nengo :: Year
        nengo = year date - startYear x + 1

-- 日付が年号の開始、終了の範囲内であるかどうか。
isBetween :: (Year, Month, Day) -> Nengo -> Bool
isBetween date nengo = date >= start nengo && date <= end nengo

startYear :: Nengo -> Year
startYear = year.start

year  :: (Year, Month, Day) -> Year
month :: (Year, Month, Day) -> Month
day   :: (Year, Month, Day) -> Day
year  (y, _, _) = y
month (_, m, _) = m
day   (_, _, d) = d
-- 明治以前はテーブルにないので・・・
> toWareki (1868, 1,24) --=> Nothing

> toWareki (1868, 1,25) --=> Just ("Meiji",(1,1,25))
> toWareki (1912, 7,29) --=> Just ("Meiji",(45,7,29))
> toWareki (1912, 7,30) --=> Just ("Taisho",(1,7,30))
> toWareki (1989, 1, 7) --=> Just ("Showa",(64,1,7))
> toWareki (1989, 1, 8) --=> Just ("Heisei",(1,1,8))
-- 存在しない日付のチェックはしていない。
> toWareki (1989, 0, 7) --=> Just ("Showa",(64,0,7))
> toWareki (1989, 0, 0) --=> Just ("Showa",(64,0,0))