{-# LANGUAGE DeriveDataTypeable #-}

{- |
Module      : Time.Diff
License     : BSD-style
Copyright   : (c) 2014 Vincent Hanquez <vincent@snarc.org>
Stability   : experimental
Portability : unknown

Time arithmetic methods.
-}

module Time.Diff
  ( Duration (..)
  , Period (..)
  , durationNormalize
  , durationFlatten
  , elapsedTimeAddSeconds
  , elapsedTimeAddSecondsP
  , dateAddPeriod
  ) where

import           Control.DeepSeq ( NFData (..) )
import           Data.Data ( Data )
import           Time.Calendar ( daysInMonth )
import           Time.Types
                   ( Date (..), Elapsed (..), ElapsedP (..), Hours (..)
                   , Minutes (..), NanoSeconds (..), Seconds (..)
                   , TimeInterval (..)
                   )

-- | Type representing periods of time in years, months and days.

-- See t'Duration' for periods of time hours, minutes, seconds and nanoseconds.

data Period = Period
  { Period -> Int
periodYears  :: !Int
  , Period -> Int
periodMonths :: !Int
  , Period -> Int
periodDays   :: !Int
  }
  deriving (Typeable Period
Typeable Period =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> Period -> c Period)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c Period)
-> (Period -> Constr)
-> (Period -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c Period))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Period))
-> ((forall b. Data b => b -> b) -> Period -> Period)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> Period -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> Period -> r)
-> (forall u. (forall d. Data d => d -> u) -> Period -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> Period -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> Period -> m Period)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Period -> m Period)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Period -> m Period)
-> Data Period
Period -> Constr
Period -> DataType
(forall b. Data b => b -> b) -> Period -> Period
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) -> Period -> u
forall u. (forall d. Data d => d -> u) -> Period -> [u]
forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Period -> r
forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Period -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Period -> m Period
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Period -> m Period
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Period
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Period -> c Period
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Period)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Period)
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Period -> c Period
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Period -> c Period
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Period
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Period
$ctoConstr :: Period -> Constr
toConstr :: Period -> Constr
$cdataTypeOf :: Period -> DataType
dataTypeOf :: Period -> DataType
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Period)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Period)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Period)
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Period)
$cgmapT :: (forall b. Data b => b -> b) -> Period -> Period
gmapT :: (forall b. Data b => b -> b) -> Period -> Period
$cgmapQl :: forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Period -> r
gmapQl :: forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Period -> r
$cgmapQr :: forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Period -> r
gmapQr :: forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Period -> r
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> Period -> [u]
gmapQ :: forall u. (forall d. Data d => d -> u) -> Period -> [u]
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Period -> u
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Period -> u
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Period -> m Period
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Period -> m Period
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Period -> m Period
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Period -> m Period
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Period -> m Period
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Period -> m Period
Data, Period -> Period -> Bool
(Period -> Period -> Bool)
-> (Period -> Period -> Bool) -> Eq Period
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Period -> Period -> Bool
== :: Period -> Period -> Bool
$c/= :: Period -> Period -> Bool
/= :: Period -> Period -> Bool
Eq, Eq Period
Eq Period =>
(Period -> Period -> Ordering)
-> (Period -> Period -> Bool)
-> (Period -> Period -> Bool)
-> (Period -> Period -> Bool)
-> (Period -> Period -> Bool)
-> (Period -> Period -> Period)
-> (Period -> Period -> Period)
-> Ord Period
Period -> Period -> Bool
Period -> Period -> Ordering
Period -> Period -> Period
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Period -> Period -> Ordering
compare :: Period -> Period -> Ordering
$c< :: Period -> Period -> Bool
< :: Period -> Period -> Bool
$c<= :: Period -> Period -> Bool
<= :: Period -> Period -> Bool
$c> :: Period -> Period -> Bool
> :: Period -> Period -> Bool
$c>= :: Period -> Period -> Bool
>= :: Period -> Period -> Bool
$cmax :: Period -> Period -> Period
max :: Period -> Period -> Period
$cmin :: Period -> Period -> Period
min :: Period -> Period -> Period
Ord, ReadPrec [Period]
ReadPrec Period
Int -> ReadS Period
ReadS [Period]
(Int -> ReadS Period)
-> ReadS [Period]
-> ReadPrec Period
-> ReadPrec [Period]
-> Read Period
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS Period
readsPrec :: Int -> ReadS Period
$creadList :: ReadS [Period]
readList :: ReadS [Period]
$creadPrec :: ReadPrec Period
readPrec :: ReadPrec Period
$creadListPrec :: ReadPrec [Period]
readListPrec :: ReadPrec [Period]
Read, Int -> Period -> ShowS
[Period] -> ShowS
Period -> String
(Int -> Period -> ShowS)
-> (Period -> String) -> ([Period] -> ShowS) -> Show Period
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Period -> ShowS
showsPrec :: Int -> Period -> ShowS
$cshow :: Period -> String
show :: Period -> String
$cshowList :: [Period] -> ShowS
showList :: [Period] -> ShowS
Show)

instance NFData Period where
  rnf :: Period -> ()
rnf (Period Int
y Int
m Int
d) = Int
y Int -> () -> ()
forall a b. a -> b -> b
`seq` Int
m Int -> () -> ()
forall a b. a -> b -> b
`seq` Int
d Int -> () -> ()
forall a b. a -> b -> b
`seq` ()

instance Semigroup Period where
  <> :: Period -> Period -> Period
(<>) (Period Int
y1 Int
m1 Int
d1) (Period Int
y2 Int
m2 Int
d2) =
    Int -> Int -> Int -> Period
Period (Int
y1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
y2) (Int
m1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
m2) (Int
d1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
d2)

instance Monoid Period where
  mempty :: Period
mempty = Int -> Int -> Int -> Period
Period Int
0 Int
0 Int
0

-- | Type represeting periods of time in hours, minutes, seconds and

-- nanoseconds. See t'Period' for periods of time in years, months and days.

data Duration = Duration
  { Duration -> Hours
durationHours   :: !Hours       -- ^ number of hours

  , Duration -> Minutes
durationMinutes :: !Minutes     -- ^ number of minutes

  , Duration -> Seconds
durationSeconds :: !Seconds     -- ^ number of seconds

  , Duration -> NanoSeconds
durationNs      :: !NanoSeconds -- ^ number of nanoseconds

  }
  deriving (Typeable Duration
Typeable Duration =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> Duration -> c Duration)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c Duration)
-> (Duration -> Constr)
-> (Duration -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c Duration))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Duration))
-> ((forall b. Data b => b -> b) -> Duration -> Duration)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> Duration -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> Duration -> r)
-> (forall u. (forall d. Data d => d -> u) -> Duration -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> Duration -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> Duration -> m Duration)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Duration -> m Duration)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Duration -> m Duration)
-> Data Duration
Duration -> Constr
Duration -> DataType
(forall b. Data b => b -> b) -> Duration -> Duration
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) -> Duration -> u
forall u. (forall d. Data d => d -> u) -> Duration -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Duration -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Duration -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Duration -> m Duration
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Duration -> m Duration
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Duration
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Duration -> c Duration
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Duration)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Duration)
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Duration -> c Duration
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Duration -> c Duration
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Duration
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Duration
$ctoConstr :: Duration -> Constr
toConstr :: Duration -> Constr
$cdataTypeOf :: Duration -> DataType
dataTypeOf :: Duration -> DataType
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Duration)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Duration)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Duration)
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Duration)
$cgmapT :: (forall b. Data b => b -> b) -> Duration -> Duration
gmapT :: (forall b. Data b => b -> b) -> Duration -> Duration
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Duration -> r
gmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Duration -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Duration -> r
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Duration -> r
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> Duration -> [u]
gmapQ :: forall u. (forall d. Data d => d -> u) -> Duration -> [u]
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Duration -> u
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Duration -> u
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Duration -> m Duration
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Duration -> m Duration
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Duration -> m Duration
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Duration -> m Duration
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Duration -> m Duration
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Duration -> m Duration
Data, Duration -> Duration -> Bool
(Duration -> Duration -> Bool)
-> (Duration -> Duration -> Bool) -> Eq Duration
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Duration -> Duration -> Bool
== :: Duration -> Duration -> Bool
$c/= :: Duration -> Duration -> Bool
/= :: Duration -> Duration -> Bool
Eq, Eq Duration
Eq Duration =>
(Duration -> Duration -> Ordering)
-> (Duration -> Duration -> Bool)
-> (Duration -> Duration -> Bool)
-> (Duration -> Duration -> Bool)
-> (Duration -> Duration -> Bool)
-> (Duration -> Duration -> Duration)
-> (Duration -> Duration -> Duration)
-> Ord Duration
Duration -> Duration -> Bool
Duration -> Duration -> Ordering
Duration -> Duration -> Duration
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Duration -> Duration -> Ordering
compare :: Duration -> Duration -> Ordering
$c< :: Duration -> Duration -> Bool
< :: Duration -> Duration -> Bool
$c<= :: Duration -> Duration -> Bool
<= :: Duration -> Duration -> Bool
$c> :: Duration -> Duration -> Bool
> :: Duration -> Duration -> Bool
$c>= :: Duration -> Duration -> Bool
>= :: Duration -> Duration -> Bool
$cmax :: Duration -> Duration -> Duration
max :: Duration -> Duration -> Duration
$cmin :: Duration -> Duration -> Duration
min :: Duration -> Duration -> Duration
Ord, ReadPrec [Duration]
ReadPrec Duration
Int -> ReadS Duration
ReadS [Duration]
(Int -> ReadS Duration)
-> ReadS [Duration]
-> ReadPrec Duration
-> ReadPrec [Duration]
-> Read Duration
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS Duration
readsPrec :: Int -> ReadS Duration
$creadList :: ReadS [Duration]
readList :: ReadS [Duration]
$creadPrec :: ReadPrec Duration
readPrec :: ReadPrec Duration
$creadListPrec :: ReadPrec [Duration]
readListPrec :: ReadPrec [Duration]
Read, Int -> Duration -> ShowS
[Duration] -> ShowS
Duration -> String
(Int -> Duration -> ShowS)
-> (Duration -> String) -> ([Duration] -> ShowS) -> Show Duration
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Duration -> ShowS
showsPrec :: Int -> Duration -> ShowS
$cshow :: Duration -> String
show :: Duration -> String
$cshowList :: [Duration] -> ShowS
showList :: [Duration] -> ShowS
Show)

instance NFData Duration where
  rnf :: Duration -> ()
rnf (Duration Hours
h Minutes
m Seconds
s NanoSeconds
ns) = Hours
h Hours -> () -> ()
forall a b. a -> b -> b
`seq` Minutes
m Minutes -> () -> ()
forall a b. a -> b -> b
`seq` Seconds
s Seconds -> () -> ()
forall a b. a -> b -> b
`seq` NanoSeconds
ns NanoSeconds -> () -> ()
forall a b. a -> b -> b
`seq` ()

instance Semigroup Duration where
  <> :: Duration -> Duration -> Duration
(<>) (Duration Hours
h1 Minutes
m1 Seconds
s1 NanoSeconds
ns1) (Duration Hours
h2 Minutes
m2 Seconds
s2 NanoSeconds
ns2) =
    Hours -> Minutes -> Seconds -> NanoSeconds -> Duration
Duration (Hours
h1 Hours -> Hours -> Hours
forall a. Num a => a -> a -> a
+ Hours
h2) (Minutes
m1 Minutes -> Minutes -> Minutes
forall a. Num a => a -> a -> a
+ Minutes
m2) (Seconds
s1 Seconds -> Seconds -> Seconds
forall a. Num a => a -> a -> a
+ Seconds
s2) (NanoSeconds
ns1 NanoSeconds -> NanoSeconds -> NanoSeconds
forall a. Num a => a -> a -> a
+ NanoSeconds
ns2)

instance Monoid Duration where
  mempty :: Duration
mempty = Hours -> Minutes -> Seconds -> NanoSeconds -> Duration
Duration Hours
0 Minutes
0 Seconds
0 NanoSeconds
0

instance TimeInterval Duration where
  fromSeconds :: Seconds -> (Duration, Seconds)
fromSeconds Seconds
s = (Duration -> Duration
durationNormalize (Hours -> Minutes -> Seconds -> NanoSeconds -> Duration
Duration Hours
0 Minutes
0 Seconds
s NanoSeconds
0), Seconds
0)

  toSeconds :: Duration -> Seconds
toSeconds Duration
d   = (Seconds, NanoSeconds) -> Seconds
forall a b. (a, b) -> a
fst ((Seconds, NanoSeconds) -> Seconds)
-> (Seconds, NanoSeconds) -> Seconds
forall a b. (a -> b) -> a -> b
$ Duration -> (Seconds, NanoSeconds)
durationFlatten Duration
d

-- | Convert a t'Duration' to an equivalent number of seconds and nanoseconds.

durationFlatten :: Duration -> (Seconds, NanoSeconds)
durationFlatten :: Duration -> (Seconds, NanoSeconds)
durationFlatten (Duration Hours
h Minutes
m Seconds
s (NanoSeconds Int64
ns)) =
  (Hours -> Seconds
forall i. TimeInterval i => i -> Seconds
toSeconds Hours
h Seconds -> Seconds -> Seconds
forall a. Num a => a -> a -> a
+ Minutes -> Seconds
forall i. TimeInterval i => i -> Seconds
toSeconds Minutes
m Seconds -> Seconds -> Seconds
forall a. Num a => a -> a -> a
+ Seconds
s Seconds -> Seconds -> Seconds
forall a. Num a => a -> a -> a
+ Int64 -> Seconds
Seconds Int64
sacc, Int64 -> NanoSeconds
NanoSeconds Int64
ns')
 where
  (Int64
sacc, Int64
ns') = Int64
ns Int64 -> Int64 -> (Int64, Int64)
forall a. Integral a => a -> a -> (a, a)
`divMod` Int64
1000000000

-- | Normalize a t'Duration' to represent the same period of time with the

-- biggest units possible. For example, 62 minutes is normalized as

-- 1 hour and 2 minutes.

durationNormalize :: Duration -> Duration
durationNormalize :: Duration -> Duration
durationNormalize (Duration (Hours Int64
h) (Minutes Int64
mi) (Seconds Int64
s) (NanoSeconds Int64
ns)) =
  Hours -> Minutes -> Seconds -> NanoSeconds -> Duration
Duration (Int64 -> Hours
Hours (Int64
hInt64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
+Int64
hacc)) (Int64 -> Minutes
Minutes Int64
mi') (Int64 -> Seconds
Seconds Int64
s') (Int64 -> NanoSeconds
NanoSeconds Int64
ns')
 where
  (Int64
hacc, Int64
mi') = (Int64
miInt64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
+Int64
miacc) Int64 -> Int64 -> (Int64, Int64)
forall a. Integral a => a -> a -> (a, a)
`divMod` Int64
60
  (Int64
miacc, Int64
s') = (Int64
sInt64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
+Int64
sacc) Int64 -> Int64 -> (Int64, Int64)
forall a. Integral a => a -> a -> (a, a)
`divMod` Int64
60
  (Int64
sacc, Int64
ns') = Int64
ns Int64 -> Int64 -> (Int64, Int64)
forall a. Integral a => a -> a -> (a, a)
`divMod` Int64
1000000000

-- | Add the given period of time to the given date.

dateAddPeriod :: Date -> Period -> Date
dateAddPeriod :: Date -> Period -> Date
dateAddPeriod (Date Int
yOrig Month
mOrig Int
dOrig) (Period Int
yDiff Int
mDiff Int
dDiff) =
  Int -> Int -> Int -> Date
loop (Int
yOrig Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
yDiff Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
yDiffAcc) Int
mStartPos (Int
dOrig Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
dDiff)
 where
  (Int
yDiffAcc,Int
mStartPos) = (Month -> Int
forall a. Enum a => a -> Int
fromEnum Month
mOrig Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
mDiff) Int -> Int -> (Int, Int)
forall a. Integral a => a -> a -> (a, a)
`divMod` Int
12
  loop :: Int -> Int -> Int -> Date
loop Int
y Int
m Int
d
    | Int
d Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 =
        let (Int
m', Int
y') = if Int
m Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0
              then (Int
11, Int
y Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
              else (Int
m Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1, Int
y)
        in  Int -> Int -> Int -> Date
loop Int
y' Int
m' (Int -> Month -> Int
daysInMonth Int
y' (Int -> Month
forall a. Enum a => Int -> a
toEnum Int
m') Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
d)
    | Int
d Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
dMonth = Int -> Month -> Int -> Date
Date Int
y (Int -> Month
forall a. Enum a => Int -> a
toEnum Int
m) Int
d
    | Bool
otherwise =
        let newDiff :: Int
newDiff = Int
d Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
dMonth
        in  if Int
m Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
11
              then Int -> Int -> Int -> Date
loop (Int
y Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Int
0 Int
newDiff
              else Int -> Int -> Int -> Date
loop Int
y (Int
m Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Int
newDiff
   where
    dMonth :: Int
dMonth = Int -> Month -> Int
daysInMonth Int
y (Int -> Month
forall a. Enum a => Int -> a
toEnum Int
m)

-- | Add the given number of seconds to the given t'Elapsed' value.

elapsedTimeAddSeconds :: Elapsed -> Seconds -> Elapsed
elapsedTimeAddSeconds :: Elapsed -> Seconds -> Elapsed
elapsedTimeAddSeconds (Elapsed Seconds
s1) Seconds
s2 = Seconds -> Elapsed
Elapsed (Seconds
s1 Seconds -> Seconds -> Seconds
forall a. Num a => a -> a -> a
+ Seconds
s2)

-- | Add the given number of seconds to the given t'ElapsedP' value.

elapsedTimeAddSecondsP :: ElapsedP -> Seconds -> ElapsedP
elapsedTimeAddSecondsP :: ElapsedP -> Seconds -> ElapsedP
elapsedTimeAddSecondsP (ElapsedP (Elapsed Seconds
s1) NanoSeconds
ns1) Seconds
s2 =
  Elapsed -> NanoSeconds -> ElapsedP
ElapsedP (Seconds -> Elapsed
Elapsed (Seconds
s1 Seconds -> Seconds -> Seconds
forall a. Num a => a -> a -> a
+ Seconds
s2)) NanoSeconds
ns1

{- disabled for warning purpose. to be implemented

-- | Duration string to time diff
--
-- <http://en.wikipedia.org/wiki/ISO_8601#Durations>
--
-- * P is the duration designator (historically called "period") placed at the start of the duration representation.
--
-- * Y is the year designator that follows the value for the number of years.
--
-- * M is the month designator that follows the value for the number of months.
--
-- * W is the week designator that follows the value for the number of weeks.
--
-- * D is the day designator that follows the value for the number of days.
--
-- * T is the time designator that precedes the time components of the representation.
--
-- * H is the hour designator that follows the value for the number of hours.
--
-- * M is the minute designator that follows the value for the number of minutes.
--
-- * S is the second designator that follows the value for the number of seconds.
--
timeDiffFromDuration :: String -> TimeDiff
timeDiffFromDuration _ = undefined

timeDiffFromString :: String -> (

-- | Human description string to time diff
--
-- examples:
--
-- * "1 day"
--
-- * "2 months, 5 days and 1 second"
--
timeDiffFromDescription :: String -> TimeDiff
timeDiffFromDescription _ = undefined
-}