RosettaCodeData/Task/Discordian-date/Haskell/discordian-date-1.hs
2016-12-05 22:15:40 +01:00

44 lines
1.3 KiB
Haskell

import Data.Time (isLeapYear)
import Data.Time.Calendar.MonthDay (monthAndDayToDayOfYear)
import Text.Printf (printf)
type Year = Integer
type Day = Int
type Month = Int
data DDate = DDate Weekday Season Day Year
| StTibsDay Year deriving (Eq, Ord)
data Season = Chaos
| Discord
| Confusion
| Bureaucracy
| TheAftermath
deriving (Show, Enum, Eq, Ord, Bounded)
data Weekday = Sweetmorn
| Boomtime
| Pungenday
| PricklePrickle
| SettingOrange
deriving (Show, Enum, Eq, Ord, Bounded)
instance Show DDate where
show (StTibsDay y) = printf "St. Tib's Day, %d YOLD" y
show (DDate w s d y) = printf "%s, %s %d, %d YOLD" (show w) (show s) d y
fromYMD :: (Year, Month, Day) -> DDate
fromYMD (y, m, d)
| leap && dayOfYear == 59 = StTibsDay yold
| leap && dayOfYear >= 60 = mkDDate $ dayOfYear - 1
| otherwise = mkDDate dayOfYear
where
yold = y + 1166
dayOfYear = monthAndDayToDayOfYear leap m d - 1
leap = isLeapYear y
mkDDate dayOfYear = DDate weekday season dayOfSeason yold
where
weekday = toEnum $ dayOfYear `mod` 5
season = toEnum $ dayOfYear `div` 73
dayOfSeason = 1 + dayOfYear `mod` 73