module Data.Time.LocalTime.Internal.CalendarDiffTime
    (
        -- * Calendar Duration
        module Data.Time.LocalTime.Internal.CalendarDiffTime
    ) where
#if MIN_VERSION_base(4,8,0)
#else
import Data.Monoid
#endif
#if MIN_VERSION_base(4,9,0) && !MIN_VERSION_base(4,11,0)
import Data.Semigroup hiding (option)
#endif
import Data.Fixed
import Data.Typeable
import Data.Data
import Data.Time.Calendar.CalendarDiffDays
import Data.Time.Clock.Internal.NominalDiffTime

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

#if MIN_VERSION_base(4,9,0)
-- | Additive
instance Semigroup CalendarDiffTime where
    CalendarDiffTime Integer
m1 NominalDiffTime
d1 <> :: CalendarDiffTime -> CalendarDiffTime -> CalendarDiffTime
<> CalendarDiffTime Integer
m2 NominalDiffTime
d2 = Integer -> NominalDiffTime -> CalendarDiffTime
CalendarDiffTime (Integer
m1 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
m2) (NominalDiffTime
d1 NominalDiffTime -> NominalDiffTime -> NominalDiffTime
forall a. Num a => a -> a -> a
+ NominalDiffTime
d2)
#endif
-- | Additive
instance Monoid CalendarDiffTime where
    mempty :: CalendarDiffTime
mempty = Integer -> NominalDiffTime -> CalendarDiffTime
CalendarDiffTime Integer
0 NominalDiffTime
0
#if MIN_VERSION_base(4,9,0)
    mappend :: CalendarDiffTime -> CalendarDiffTime -> CalendarDiffTime
mappend = CalendarDiffTime -> CalendarDiffTime -> CalendarDiffTime
forall a. Semigroup a => a -> a -> a
(<>)
#else
    mappend (CalendarDiffTime m1 d1) (CalendarDiffTime m2 d2) = CalendarDiffTime (m1 + m2) (d1 + d2)
#endif

instance Show CalendarDiffTime where
    show :: CalendarDiffTime -> String
show (CalendarDiffTime Integer
m NominalDiffTime
t) = 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
"MT" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Bool -> Fixed E12 -> String
forall k (a :: k). HasResolution a => Bool -> Fixed a -> String
showFixed Bool
True (NominalDiffTime -> Fixed E12
forall a b. (Real a, Fractional b) => a -> b
realToFrac NominalDiffTime
t :: Pico) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"S"

calendarTimeDays :: CalendarDiffDays -> CalendarDiffTime
calendarTimeDays :: CalendarDiffDays -> CalendarDiffTime
calendarTimeDays (CalendarDiffDays Integer
m Integer
d) = Integer -> NominalDiffTime -> CalendarDiffTime
CalendarDiffTime Integer
m (NominalDiffTime -> CalendarDiffTime)
-> NominalDiffTime -> CalendarDiffTime
forall a b. (a -> b) -> a -> b
$ Integer -> NominalDiffTime
forall a. Num a => Integer -> a
fromInteger Integer
d NominalDiffTime -> NominalDiffTime -> NominalDiffTime
forall a. Num a => a -> a -> a
* NominalDiffTime
nominalDay

calendarTimeTime :: NominalDiffTime -> CalendarDiffTime
calendarTimeTime :: NominalDiffTime -> CalendarDiffTime
calendarTimeTime NominalDiffTime
dt = Integer -> NominalDiffTime -> CalendarDiffTime
CalendarDiffTime Integer
0 NominalDiffTime
dt

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