-----------------------------------------------------------------------------
-- |
-- Module      :  Data.HodaTime.Interval
-- Copyright   :  (C) 2016 Jason Johnson
-- License     :  BSD-style (see the file LICENSE)
-- Maintainer  :  Jason Johnson <jason.johnson.081@gmail.com>
-- Stability   :  experimental
-- Portability :  TBD
--
-- An 'Interval' is a period of time between two 'Instant's.
----------------------------------------------------------------------------
module Data.HodaTime.Interval
(
  -- * Types
  Interval
  -- * Constructor
  ,interval
  -- * Lenses
  ,start
  ,end
  -- * Functions
  ,contains
  ,duration
)
where

import Data.HodaTime.Instant.Internal (Instant)
import Data.HodaTime.Duration.Internal (Duration)
import Data.HodaTime.Instant (difference)

data Interval = Interval Instant Instant
    deriving (Interval -> Interval -> Bool
(Interval -> Interval -> Bool)
-> (Interval -> Interval -> Bool) -> Eq Interval
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Interval -> Interval -> Bool
== :: Interval -> Interval -> Bool
$c/= :: Interval -> Interval -> Bool
/= :: Interval -> Interval -> Bool
Eq, Eq Interval
Eq Interval =>
(Interval -> Interval -> Ordering)
-> (Interval -> Interval -> Bool)
-> (Interval -> Interval -> Bool)
-> (Interval -> Interval -> Bool)
-> (Interval -> Interval -> Bool)
-> (Interval -> Interval -> Interval)
-> (Interval -> Interval -> Interval)
-> Ord Interval
Interval -> Interval -> Bool
Interval -> Interval -> Ordering
Interval -> Interval -> Interval
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 :: Interval -> Interval -> Ordering
compare :: Interval -> Interval -> Ordering
$c< :: Interval -> Interval -> Bool
< :: Interval -> Interval -> Bool
$c<= :: Interval -> Interval -> Bool
<= :: Interval -> Interval -> Bool
$c> :: Interval -> Interval -> Bool
> :: Interval -> Interval -> Bool
$c>= :: Interval -> Interval -> Bool
>= :: Interval -> Interval -> Bool
$cmax :: Interval -> Interval -> Interval
max :: Interval -> Interval -> Interval
$cmin :: Interval -> Interval -> Interval
min :: Interval -> Interval -> Interval
Ord, Int -> Interval -> ShowS
[Interval] -> ShowS
Interval -> String
(Int -> Interval -> ShowS)
-> (Interval -> String) -> ([Interval] -> ShowS) -> Show Interval
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Interval -> ShowS
showsPrec :: Int -> Interval -> ShowS
$cshow :: Interval -> String
show :: Interval -> String
$cshowList :: [Interval] -> ShowS
showList :: [Interval] -> ShowS
Show)    -- TODO: Remove Show

interval :: Instant -> Instant -> Interval
interval :: Instant -> Instant -> Interval
interval = Instant -> Instant -> Interval
Interval             -- TODO: We probably need some checks here

-- | Lens for the start component of the 'Interval'
start :: Functor f => (Instant -> f Instant) -> Interval -> f Interval
start :: forall (f :: * -> *).
Functor f =>
(Instant -> f Instant) -> Interval -> f Interval
start Instant -> f Instant
f (Interval Instant
s Instant
e) = (Instant -> Instant -> Interval) -> Instant -> Instant -> Interval
forall a b c. (a -> b -> c) -> b -> a -> c
flip Instant -> Instant -> Interval
Interval Instant
e (Instant -> Interval) -> f Instant -> f Interval
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Instant -> f Instant
f Instant
s
{-# INLINE start #-}

-- | Lens for the end component of the 'Interval'
end :: Functor f => (Instant -> f Instant) -> Interval -> f Interval
end :: forall (f :: * -> *).
Functor f =>
(Instant -> f Instant) -> Interval -> f Interval
end Instant -> f Instant
f (Interval Instant
s Instant
e) = Instant -> Instant -> Interval
Interval Instant
s (Instant -> Interval) -> f Instant -> f Interval
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Instant -> f Instant
f Instant
e
{-# INLINE end #-}

-- | Determines if the 'Instant' is between the start and end of the 'Interval'.  The interval includes the start but excludes the end
contains :: Interval -> Instant -> Bool
contains :: Interval -> Instant -> Bool
contains (Interval Instant
s Instant
e) Instant
i = Instant
s Instant -> Instant -> Bool
forall a. Ord a => a -> a -> Bool
<= Instant
i Bool -> Bool -> Bool
&& Instant
e Instant -> Instant -> Bool
forall a. Ord a => a -> a -> Bool
> Instant
i

-- | Get the 'Duration' between the start and the end of the 'Interval'
duration :: Interval -> Duration
duration :: Interval -> Duration
duration (Interval Instant
s Instant
e) = Instant
e Instant -> Instant -> Duration
`difference` Instant
s