{-# LANGUAGE CPP #-} {-# LANGUAGE RecordWildCards #-} #include "thyme.h" -- | Proleptic Julian Dates module Data.Thyme.Calendar.Julian ( OrdinalDate (..), Year, DayOfYear , module Data.Thyme.Calendar.Julian , _odYear, _odDay ) where import Prelude import Control.Applicative {- import Control.DeepSeq -} import Control.Monad import Control.Lens {- import Data.Data -} import Data.Thyme.Calendar import Data.Thyme.Calendar.Internal import Data.Thyme.Calendar.OrdinalDate {- import Data.Thyme.TH -} {- import System.Random -} {- import Test.QuickCheck -} {-# INLINE julianOrdinal #-} julianOrdinal :: Iso' Day OrdinalDate julianOrdinal = iso toOrdinal fromOrdinal where {-# INLINEABLE toOrdinal #-} toOrdinal :: Day -> OrdinalDate toOrdinal (ModifiedJulianDay mjd) = OrdinalDate {..} where (quad, d) = divMod (mjd + 678577) 1461 yoff = min (div d 365) 3 odDay = d - (yoff * 365) + 1 odYear = quad * 4 + yoff + 1 {-# INLINEABLE fromOrdinal #-} fromOrdinal :: OrdinalDate -> Day fromOrdinal OrdinalDate {..} = ModifiedJulianDay mjd where yd = clip 1 (if isJulianLeapYear odYear then 366 else 365) odDay clip a b = max a . min b y = odYear - 1 mjd = yd + 365 * y + div y 4 - 678578 {-# INLINEABLE julianOrdinalValid #-} julianOrdinalValid :: OrdinalDate -> Maybe Day julianOrdinalValid OrdinalDate {..} = ModifiedJulianDay mjd <$ guard (1 <= odDay && odDay <= lastDay) where lastDay = if isJulianLeapYear odYear then 366 else 365 y = odYear - 1 mjd = odDay + 365 * y + div y 4 - 678578 {-# INLINE isJulianLeapYear #-} isJulianLeapYear :: Year -> Bool isJulianLeapYear y = mod y 4 == 0 ------------------------------------------------------------------------ {-# INLINE julianYearMonthDay #-} julianYearMonthDay :: Iso' OrdinalDate YearMonthDay julianYearMonthDay = iso fromOrdinal toOrdinal where {-# INLINEABLE fromOrdinal #-} fromOrdinal :: OrdinalDate -> YearMonthDay fromOrdinal OrdinalDate {..} = YearMonthDay odYear m d where MonthDay m d = odDay ^. monthDay (isJulianLeapYear odYear) {-# INLINEABLE toOrdinal #-} toOrdinal :: YearMonthDay -> OrdinalDate toOrdinal YearMonthDay {..} = OrdinalDate ymdYear yd where yd = monthDay (isJulianLeapYear ymdYear) # MonthDay ymdMonth ymdDay {-# INLINE julianYearMonthDayValid #-} julianYearMonthDayValid :: YearMonthDay -> Maybe OrdinalDate julianYearMonthDayValid YearMonthDay {..} = OrdinalDate ymdYear <$> monthDayValid (isJulianLeapYear ymdYear) (MonthDay ymdMonth ymdDay) ------------------------------------------------------------------------ {-# INLINE julian #-} julian :: Iso' Day YearMonthDay julian = julianOrdinal . julianYearMonthDay {-# INLINE julianValid #-} julianValid :: YearMonthDay -> Maybe Day julianValid ymd = review julianOrdinal <$> julianYearMonthDayValid ymd