{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveDataTypeable #-}
#if __GLASGOW_HASKELL__ >= 710
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE ViewPatterns #-}
#endif
module Data.Time.Calendar.Compat (
Day(..),addDays,diffDays,
CalendarDiffDays (..),
calendarDay,calendarWeek,calendarMonth,calendarYear,scaleCalendarDiffDays,
toGregorian,fromGregorian,fromGregorianValid,showGregorian,gregorianMonthLength,
addGregorianMonthsClip,addGregorianMonthsRollOver,
addGregorianYearsClip,addGregorianYearsRollOver,
addGregorianDurationClip,addGregorianDurationRollOver,
diffGregorianDurationClip,diffGregorianDurationRollOver,
isLeapYear ,
DayOfWeek(..), dayOfWeek,
dayOfWeekDiff, firstDayOfWeekOnAfter,
DayOfMonth, MonthOfYear, Year,
#if __GLASGOW_HASKELL__ >= 710
pattern YearMonthDay,
#endif
) where
import Data.Time.Calendar
import Data.Time.Format
import Data.Time.Orphans ()
#if !MIN_VERSION_time(1,11,0)
import Data.Time.Calendar.Types
#endif
#if !MIN_VERSION_time(1,9,0)
import Data.Time.Calendar.WeekDate.Compat
#endif
#if !MIN_VERSION_time(1,5,0)
import System.Locale (TimeLocale (..))
#endif
import Control.DeepSeq (NFData (..))
import Data.Data (Data, Typeable)
import Data.Monoid (Monoid (..))
import Data.Semigroup (Semigroup (..))
#if MIN_VERSION_time(1,9,0) && !MIN_VERSION_time(1,9,2)
deriving instance Typeable CalendarDiffDays
deriving instance Data CalendarDiffDays
#endif
#if !MIN_VERSION_time(1,9,0)
data CalendarDiffDays = CalendarDiffDays
{ cdMonths :: Integer
, cdDays :: Integer
} deriving (Eq,
Data
#if __GLASGOW_HASKELL__ >= 802
#endif
,Typeable
#if __GLASGOW_HASKELL__ >= 802
#endif
)
instance Semigroup CalendarDiffDays where
CalendarDiffDays m1 d1 <> CalendarDiffDays m2 d2 = CalendarDiffDays (m1 + m2) (d1 + d2)
instance Monoid CalendarDiffDays where
mempty = CalendarDiffDays 0 0
mappend = (<>)
instance Show CalendarDiffDays where
show (CalendarDiffDays m d) = "P" ++ show m ++ "M" ++ show d ++ "D"
instance NFData CalendarDiffDays where
rnf (CalendarDiffDays x y) = rnf x `seq` rnf y
calendarDay :: CalendarDiffDays
calendarDay = CalendarDiffDays 0 1
calendarWeek :: CalendarDiffDays
calendarWeek = CalendarDiffDays 0 7
calendarMonth :: CalendarDiffDays
calendarMonth = CalendarDiffDays 1 0
calendarYear :: CalendarDiffDays
calendarYear = CalendarDiffDays 12 0
scaleCalendarDiffDays :: Integer -> CalendarDiffDays -> CalendarDiffDays
scaleCalendarDiffDays k (CalendarDiffDays m d) = CalendarDiffDays (k * m) (k * d)
#endif
#if !MIN_VERSION_time(1,9,0)
addGregorianDurationClip :: CalendarDiffDays -> Day -> Day
addGregorianDurationClip (CalendarDiffDays m d) day = addDays d $ addGregorianMonthsClip m day
addGregorianDurationRollOver :: CalendarDiffDays -> Day -> Day
addGregorianDurationRollOver (CalendarDiffDays m d) day = addDays d $ addGregorianMonthsRollOver m day
diffGregorianDurationClip :: Day -> Day -> CalendarDiffDays
diffGregorianDurationClip day2 day1 = let
(y1,m1,d1) = toGregorian day1
(y2,m2,d2) = toGregorian day2
ym1 = y1 * 12 + toInteger m1
ym2 = y2 * 12 + toInteger m2
ymdiff = ym2 - ym1
ymAllowed =
if day2 >= day1 then
if d2 >= d1 then ymdiff else ymdiff - 1
else if d2 <= d1 then ymdiff else ymdiff + 1
dayAllowed = addGregorianDurationClip (CalendarDiffDays ymAllowed 0) day1
in CalendarDiffDays ymAllowed $ diffDays day2 dayAllowed
diffGregorianDurationRollOver :: Day -> Day -> CalendarDiffDays
diffGregorianDurationRollOver day2 day1 = let
(y1,m1,d1) = toGregorian day1
(y2,m2,d2) = toGregorian day2
ym1 = y1 * 12 + toInteger m1
ym2 = y2 * 12 + toInteger m2
ymdiff = ym2 - ym1
ymAllowed =
if day2 >= day1 then
if d2 >= d1 then ymdiff else ymdiff - 1
else if d2 <= d1 then ymdiff else ymdiff + 1
dayAllowed = addGregorianDurationRollOver (CalendarDiffDays ymAllowed 0) day1
in CalendarDiffDays ymAllowed $ diffDays day2 dayAllowed
#endif
#if !MIN_VERSION_time(1,11,0)
#if __GLASGOW_HASKELL__ >= 710
pattern YearMonthDay :: Year -> MonthOfYear -> DayOfMonth -> Day
pattern $bYearMonthDay :: Year -> MonthOfYear -> MonthOfYear -> Day
$mYearMonthDay :: forall r.
Day
-> (Year -> MonthOfYear -> MonthOfYear -> r) -> (Void# -> r) -> r
YearMonthDay y m d <- (toGregorian -> (y,m,d)) where
YearMonthDay Year
y MonthOfYear
m MonthOfYear
d = Year -> MonthOfYear -> MonthOfYear -> Day
fromGregorian Year
y MonthOfYear
m MonthOfYear
d
#if __GLASGOW_HASKELL__ >= 802
{-# COMPLETE YearMonthDay #-}
#endif
#endif
#endif
#if !MIN_VERSION_time(1,11,0)
dayOfWeekDiff :: DayOfWeek -> DayOfWeek -> Int
dayOfWeekDiff :: DayOfWeek -> DayOfWeek -> MonthOfYear
dayOfWeekDiff DayOfWeek
a DayOfWeek
b = MonthOfYear -> MonthOfYear -> MonthOfYear
forall a. Integral a => a -> a -> a
mod (DayOfWeek -> MonthOfYear
forall a. Enum a => a -> MonthOfYear
fromEnum DayOfWeek
a MonthOfYear -> MonthOfYear -> MonthOfYear
forall a. Num a => a -> a -> a
- DayOfWeek -> MonthOfYear
forall a. Enum a => a -> MonthOfYear
fromEnum DayOfWeek
b) MonthOfYear
7
firstDayOfWeekOnAfter :: DayOfWeek -> Day -> Day
firstDayOfWeekOnAfter :: DayOfWeek -> Day -> Day
firstDayOfWeekOnAfter DayOfWeek
dw Day
d = Year -> Day -> Day
addDays (MonthOfYear -> Year
forall a. Integral a => a -> Year
toInteger (MonthOfYear -> Year) -> MonthOfYear -> Year
forall a b. (a -> b) -> a -> b
$ DayOfWeek -> DayOfWeek -> MonthOfYear
dayOfWeekDiff DayOfWeek
dw (DayOfWeek -> MonthOfYear) -> DayOfWeek -> MonthOfYear
forall a b. (a -> b) -> a -> b
$ Day -> DayOfWeek
dayOfWeek Day
d) Day
d
#endif