{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE TemplateHaskell #-} -- | Julian or Gregorian. module Data.Thyme.Calendar.MonthDay ( Month, DayOfMonth , module Data.Thyme.Calendar.MonthDay ) where import Prelude import Control.Applicative import Control.DeepSeq import Control.Lens import Control.Monad import Data.Data import qualified Data.Time.Calendar.MonthDay as T import Data.Thyme.Calendar.Internal import Data.Thyme.TH data MonthDay = MonthDay { mdMonth :: {-# UNPACK #-}!Month , mdDay :: {-# UNPACK #-}!DayOfMonth } deriving (Eq, Ord, Data, Typeable, Show) instance NFData MonthDay -- | Convert between day of year in the Gregorian or Julian calendars, and -- month and day of month. First arg is leap year flag. {-# INLINE monthDay #-} monthDay :: Bool -> Simple Iso DayOfYear MonthDay monthDay leap = iso fromOrdinal toOrdinal where -- TODO: Calls non-inlineable code from @time@. Pilfer and optimise? {-# INLINE fromOrdinal #-} fromOrdinal :: DayOfYear -> MonthDay fromOrdinal yd = MonthDay m d where (m, d) = T.dayOfYearToMonthAndDay leap yd {-# INLINE toOrdinal #-} toOrdinal :: MonthDay -> DayOfYear toOrdinal (MonthDay m d) = T.monthAndDayToDayOfYear leap m d {-# INLINEABLE monthDayToDayOfYearValid #-} monthDayToDayOfYearValid :: Bool -> MonthDay -> Maybe DayOfYear monthDayToDayOfYearValid leap md@(MonthDay m d) = review (monthDay leap) md <$ guard (1 <= m && m <= 12 && 1 <= d && d <= T.monthLength leap m) {-# INLINE monthLength #-} monthLength :: Bool -> Month -> Int monthLength = T.monthLength -- * Lenses thymeLenses ''MonthDay