{-# LANGUAGE Safe #-}

module Data.Time.LocalTime.Internal.CalendarDiffTime (
    -- * Calendar Duration
    module Data.Time.LocalTime.Internal.CalendarDiffTime,
) where

import Control.DeepSeq
import Data.Data
import Data.Fixed
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
$c== :: CalendarDiffTime -> CalendarDiffTime -> Bool
== :: CalendarDiffTime -> CalendarDiffTime -> Bool
$c/= :: CalendarDiffTime -> CalendarDiffTime -> Bool
/= :: CalendarDiffTime -> CalendarDiffTime -> Bool
Eq
        , -- | @since 1.9.2
          Typeable CalendarDiffTime
Typeable CalendarDiffTime
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> CalendarDiffTime -> c CalendarDiffTime)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c CalendarDiffTime)
-> (CalendarDiffTime -> Constr)
-> (CalendarDiffTime -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c CalendarDiffTime))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c CalendarDiffTime))
-> ((forall b. Data b => b -> b)
    -> CalendarDiffTime -> CalendarDiffTime)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> CalendarDiffTime -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> CalendarDiffTime -> r)
-> (forall u.
    (forall d. Data d => d -> u) -> CalendarDiffTime -> [u])
-> (forall u.
    Int -> (forall d. Data d => d -> u) -> CalendarDiffTime -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d)
    -> CalendarDiffTime -> m CalendarDiffTime)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d)
    -> CalendarDiffTime -> m CalendarDiffTime)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d)
    -> CalendarDiffTime -> m CalendarDiffTime)
-> Data CalendarDiffTime
CalendarDiffTime -> Constr
CalendarDiffTime -> DataType
(forall b. Data b => b -> b)
-> CalendarDiffTime -> CalendarDiffTime
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u.
Int -> (forall d. Data d => d -> u) -> CalendarDiffTime -> u
forall u. (forall d. Data d => d -> u) -> CalendarDiffTime -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> CalendarDiffTime -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> CalendarDiffTime -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d)
-> CalendarDiffTime -> m CalendarDiffTime
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> CalendarDiffTime -> m CalendarDiffTime
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c CalendarDiffTime
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> CalendarDiffTime -> c CalendarDiffTime
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c CalendarDiffTime)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c CalendarDiffTime)
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> CalendarDiffTime -> c CalendarDiffTime
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> CalendarDiffTime -> c CalendarDiffTime
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c CalendarDiffTime
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c CalendarDiffTime
$ctoConstr :: CalendarDiffTime -> Constr
toConstr :: CalendarDiffTime -> Constr
$cdataTypeOf :: CalendarDiffTime -> DataType
dataTypeOf :: CalendarDiffTime -> DataType
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c CalendarDiffTime)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c CalendarDiffTime)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c CalendarDiffTime)
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c CalendarDiffTime)
$cgmapT :: (forall b. Data b => b -> b)
-> CalendarDiffTime -> CalendarDiffTime
gmapT :: (forall b. Data b => b -> b)
-> CalendarDiffTime -> CalendarDiffTime
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> CalendarDiffTime -> r
gmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> CalendarDiffTime -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> CalendarDiffTime -> r
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> CalendarDiffTime -> r
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> CalendarDiffTime -> [u]
gmapQ :: forall u. (forall d. Data d => d -> u) -> CalendarDiffTime -> [u]
$cgmapQi :: forall u.
Int -> (forall d. Data d => d -> u) -> CalendarDiffTime -> u
gmapQi :: forall u.
Int -> (forall d. Data d => d -> u) -> CalendarDiffTime -> u
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d)
-> CalendarDiffTime -> m CalendarDiffTime
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d)
-> CalendarDiffTime -> m CalendarDiffTime
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> CalendarDiffTime -> m CalendarDiffTime
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> CalendarDiffTime -> m CalendarDiffTime
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> CalendarDiffTime -> m CalendarDiffTime
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> CalendarDiffTime -> m CalendarDiffTime
Data
        , -- | @since 1.9.2
          Typeable
        )

instance NFData CalendarDiffTime where
    rnf :: CalendarDiffTime -> ()
rnf (CalendarDiffTime Integer
m NominalDiffTime
t) = Integer -> ()
forall a. NFData a => a -> ()
rnf Integer
m () -> () -> ()
forall a b. a -> b -> b
`seq` NominalDiffTime -> ()
forall a. NFData a => a -> ()
rnf NominalDiffTime
t () -> () -> ()
forall a b. a -> b -> b
`seq` ()

-- | 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)

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

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 -> Pico -> String
forall {k} (a :: k). HasResolution a => Bool -> Fixed a -> String
showFixed Bool
True (NominalDiffTime -> Pico
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)