{-# LANGUAGE Safe #-}

module Data.Time.Calendar.CalendarDiffDays
    (
        -- * Calendar Duration
        module Data.Time.Calendar.CalendarDiffDays
    ) where

#if MIN_VERSION_base(4,11,0)
#else
import Data.Semigroup hiding (option)
#endif
import Data.Typeable
import Data.Data
import Control.DeepSeq

data CalendarDiffDays = CalendarDiffDays
    { CalendarDiffDays -> Integer
cdMonths :: Integer
    , CalendarDiffDays -> Integer
cdDays :: Integer
    } deriving (CalendarDiffDays -> CalendarDiffDays -> Bool
(CalendarDiffDays -> CalendarDiffDays -> Bool)
-> (CalendarDiffDays -> CalendarDiffDays -> Bool)
-> Eq CalendarDiffDays
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CalendarDiffDays -> CalendarDiffDays -> Bool
$c/= :: CalendarDiffDays -> CalendarDiffDays -> Bool
== :: CalendarDiffDays -> CalendarDiffDays -> Bool
$c== :: CalendarDiffDays -> CalendarDiffDays -> Bool
Eq,
    Data
#if __GLASGOW_HASKELL__ >= 802
    -- ^ @since 1.9.2
#endif
    ,Typeable
#if __GLASGOW_HASKELL__ >= 802
    -- ^ @since 1.9.2
#endif
    )

instance NFData CalendarDiffDays where
    rnf :: CalendarDiffDays -> ()
rnf (CalendarDiffDays Integer
m Integer
d) = Integer -> ()
forall a. NFData a => a -> ()
rnf Integer
m () -> () -> ()
`seq` Integer -> ()
forall a. NFData a => a -> ()
rnf Integer
d () -> () -> ()
`seq` ()

-- | Additive
instance Semigroup CalendarDiffDays where
    CalendarDiffDays Integer
m1 Integer
d1 <> :: CalendarDiffDays -> CalendarDiffDays -> CalendarDiffDays
<> CalendarDiffDays Integer
m2 Integer
d2 = Integer -> Integer -> CalendarDiffDays
CalendarDiffDays (Integer
m1 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
m2) (Integer
d1 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
d2)

-- | Additive
instance Monoid CalendarDiffDays where
    mempty :: CalendarDiffDays
mempty = Integer -> Integer -> CalendarDiffDays
CalendarDiffDays Integer
0 Integer
0
    mappend :: CalendarDiffDays -> CalendarDiffDays -> CalendarDiffDays
mappend = CalendarDiffDays -> CalendarDiffDays -> CalendarDiffDays
forall a. Semigroup a => a -> a -> a
(<>)

instance Show CalendarDiffDays where
    show :: CalendarDiffDays -> String
show (CalendarDiffDays Integer
m Integer
d) = String
"P" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Integer -> String
forall a. Show a => a -> String
show Integer
m String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"M" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Integer -> String
forall a. Show a => a -> String
show Integer
d String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"D"

calendarDay :: CalendarDiffDays
calendarDay :: CalendarDiffDays
calendarDay = Integer -> Integer -> CalendarDiffDays
CalendarDiffDays Integer
0 Integer
1

calendarWeek :: CalendarDiffDays
calendarWeek :: CalendarDiffDays
calendarWeek = Integer -> Integer -> CalendarDiffDays
CalendarDiffDays Integer
0 Integer
7

calendarMonth :: CalendarDiffDays
calendarMonth :: CalendarDiffDays
calendarMonth = Integer -> Integer -> CalendarDiffDays
CalendarDiffDays Integer
1 Integer
0

calendarYear :: CalendarDiffDays
calendarYear :: CalendarDiffDays
calendarYear = Integer -> Integer -> CalendarDiffDays
CalendarDiffDays Integer
12 Integer
0

-- | Scale by a factor. Note that @scaleCalendarDiffDays (-1)@ will not perfectly invert a duration, due to variable month lengths.
scaleCalendarDiffDays :: Integer -> CalendarDiffDays -> CalendarDiffDays
scaleCalendarDiffDays :: Integer -> CalendarDiffDays -> CalendarDiffDays
scaleCalendarDiffDays Integer
k (CalendarDiffDays Integer
m Integer
d) = Integer -> Integer -> CalendarDiffDays
CalendarDiffDays (Integer
k Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
m) (Integer
k Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
d)