{-# LANGUAGE Safe #-}

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

import Control.DeepSeq
import Data.Data

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
        , -- | @since 1.9.2
          Data
        , -- | @since 1.9.2
          Typeable
        )

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)