{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE Trustworthy #-}

module Data.Time.Clock.Internal.DiffTime (
    -- * Absolute intervals
    DiffTime,
    secondsToDiffTime,
    picosecondsToDiffTime,
    diffTimeToPicoseconds,
) where

import Control.DeepSeq
import Data.Data
import Data.Fixed
import GHC.Read
import qualified Language.Haskell.TH.Syntax as TH
import Text.ParserCombinators.ReadP
import Text.ParserCombinators.ReadPrec

-- | This is a length of time, as measured by a clock.
-- Conversion functions such as 'fromInteger' and 'realToFrac' will treat it as seconds.
-- For example, @(0.010 :: DiffTime)@ corresponds to 10 milliseconds.
--
-- It has a precision of one picosecond (= 10^-12 s). Enumeration functions will treat it as picoseconds.
newtype DiffTime
    = MkDiffTime Pico
    deriving (DiffTime -> DiffTime -> Bool
(DiffTime -> DiffTime -> Bool)
-> (DiffTime -> DiffTime -> Bool) -> Eq DiffTime
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: DiffTime -> DiffTime -> Bool
== :: DiffTime -> DiffTime -> Bool
$c/= :: DiffTime -> DiffTime -> Bool
/= :: DiffTime -> DiffTime -> Bool
Eq, Eq DiffTime
Eq DiffTime =>
(DiffTime -> DiffTime -> Ordering)
-> (DiffTime -> DiffTime -> Bool)
-> (DiffTime -> DiffTime -> Bool)
-> (DiffTime -> DiffTime -> Bool)
-> (DiffTime -> DiffTime -> Bool)
-> (DiffTime -> DiffTime -> DiffTime)
-> (DiffTime -> DiffTime -> DiffTime)
-> Ord DiffTime
DiffTime -> DiffTime -> Bool
DiffTime -> DiffTime -> Ordering
DiffTime -> DiffTime -> DiffTime
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 :: DiffTime -> DiffTime -> Ordering
compare :: DiffTime -> DiffTime -> Ordering
$c< :: DiffTime -> DiffTime -> Bool
< :: DiffTime -> DiffTime -> Bool
$c<= :: DiffTime -> DiffTime -> Bool
<= :: DiffTime -> DiffTime -> Bool
$c> :: DiffTime -> DiffTime -> Bool
> :: DiffTime -> DiffTime -> Bool
$c>= :: DiffTime -> DiffTime -> Bool
>= :: DiffTime -> DiffTime -> Bool
$cmax :: DiffTime -> DiffTime -> DiffTime
max :: DiffTime -> DiffTime -> DiffTime
$cmin :: DiffTime -> DiffTime -> DiffTime
min :: DiffTime -> DiffTime -> DiffTime
Ord, Typeable DiffTime
Typeable DiffTime =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> DiffTime -> c DiffTime)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c DiffTime)
-> (DiffTime -> Constr)
-> (DiffTime -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c DiffTime))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c DiffTime))
-> ((forall b. Data b => b -> b) -> DiffTime -> DiffTime)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> DiffTime -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> DiffTime -> r)
-> (forall u. (forall d. Data d => d -> u) -> DiffTime -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> DiffTime -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> DiffTime -> m DiffTime)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> DiffTime -> m DiffTime)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> DiffTime -> m DiffTime)
-> Data DiffTime
DiffTime -> Constr
DiffTime -> DataType
(forall b. Data b => b -> b) -> DiffTime -> DiffTime
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) -> DiffTime -> u
forall u. (forall d. Data d => d -> u) -> DiffTime -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> DiffTime -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> DiffTime -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> DiffTime -> m DiffTime
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> DiffTime -> m DiffTime
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c DiffTime
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> DiffTime -> c DiffTime
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c DiffTime)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c DiffTime)
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> DiffTime -> c DiffTime
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> DiffTime -> c DiffTime
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c DiffTime
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c DiffTime
$ctoConstr :: DiffTime -> Constr
toConstr :: DiffTime -> Constr
$cdataTypeOf :: DiffTime -> DataType
dataTypeOf :: DiffTime -> DataType
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c DiffTime)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c DiffTime)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c DiffTime)
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c DiffTime)
$cgmapT :: (forall b. Data b => b -> b) -> DiffTime -> DiffTime
gmapT :: (forall b. Data b => b -> b) -> DiffTime -> DiffTime
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> DiffTime -> r
gmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> DiffTime -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> DiffTime -> r
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> DiffTime -> r
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> DiffTime -> [u]
gmapQ :: forall u. (forall d. Data d => d -> u) -> DiffTime -> [u]
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> DiffTime -> u
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> DiffTime -> u
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> DiffTime -> m DiffTime
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> DiffTime -> m DiffTime
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> DiffTime -> m DiffTime
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> DiffTime -> m DiffTime
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> DiffTime -> m DiffTime
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> DiffTime -> m DiffTime
Data, Typeable)

instance NFData DiffTime where
    rnf :: DiffTime -> ()
rnf (MkDiffTime Pico
t) = Pico -> ()
forall a. NFData a => a -> ()
rnf Pico
t

instance Enum DiffTime where
    succ :: DiffTime -> DiffTime
succ (MkDiffTime Pico
a) = Pico -> DiffTime
MkDiffTime (Pico -> Pico
forall a. Enum a => a -> a
succ Pico
a)
    pred :: DiffTime -> DiffTime
pred (MkDiffTime Pico
a) = Pico -> DiffTime
MkDiffTime (Pico -> Pico
forall a. Enum a => a -> a
pred Pico
a)
    toEnum :: Int -> DiffTime
toEnum = Pico -> DiffTime
MkDiffTime (Pico -> DiffTime) -> (Int -> Pico) -> Int -> DiffTime
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Pico
forall a. Enum a => Int -> a
toEnum
    fromEnum :: DiffTime -> Int
fromEnum (MkDiffTime Pico
a) = Pico -> Int
forall a. Enum a => a -> Int
fromEnum Pico
a
    enumFrom :: DiffTime -> [DiffTime]
enumFrom (MkDiffTime Pico
a) = (Pico -> DiffTime) -> [Pico] -> [DiffTime]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Pico -> DiffTime
MkDiffTime (Pico -> [Pico]
forall a. Enum a => a -> [a]
enumFrom Pico
a)
    enumFromThen :: DiffTime -> DiffTime -> [DiffTime]
enumFromThen (MkDiffTime Pico
a) (MkDiffTime Pico
b) = (Pico -> DiffTime) -> [Pico] -> [DiffTime]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Pico -> DiffTime
MkDiffTime (Pico -> Pico -> [Pico]
forall a. Enum a => a -> a -> [a]
enumFromThen Pico
a Pico
b)
    enumFromTo :: DiffTime -> DiffTime -> [DiffTime]
enumFromTo (MkDiffTime Pico
a) (MkDiffTime Pico
b) = (Pico -> DiffTime) -> [Pico] -> [DiffTime]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Pico -> DiffTime
MkDiffTime (Pico -> Pico -> [Pico]
forall a. Enum a => a -> a -> [a]
enumFromTo Pico
a Pico
b)
    enumFromThenTo :: DiffTime -> DiffTime -> DiffTime -> [DiffTime]
enumFromThenTo (MkDiffTime Pico
a) (MkDiffTime Pico
b) (MkDiffTime Pico
c) = (Pico -> DiffTime) -> [Pico] -> [DiffTime]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Pico -> DiffTime
MkDiffTime (Pico -> Pico -> Pico -> [Pico]
forall a. Enum a => a -> a -> a -> [a]
enumFromThenTo Pico
a Pico
b Pico
c)

instance Show DiffTime where
    show :: DiffTime -> String
show (MkDiffTime Pico
t) = (Bool -> Pico -> String
forall {k} (a :: k). HasResolution a => Bool -> Fixed a -> String
showFixed Bool
True Pico
t) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"s"

instance Read DiffTime where
    readPrec :: ReadPrec DiffTime
readPrec = do
        t <- ReadPrec Pico
forall a. Read a => ReadPrec a
readPrec
        _ <- lift $ char 's'
        return $ MkDiffTime t

instance Num DiffTime where
    (MkDiffTime Pico
a) + :: DiffTime -> DiffTime -> DiffTime
+ (MkDiffTime Pico
b) = Pico -> DiffTime
MkDiffTime (Pico
a Pico -> Pico -> Pico
forall a. Num a => a -> a -> a
+ Pico
b)
    (MkDiffTime Pico
a) - :: DiffTime -> DiffTime -> DiffTime
- (MkDiffTime Pico
b) = Pico -> DiffTime
MkDiffTime (Pico
a Pico -> Pico -> Pico
forall a. Num a => a -> a -> a
- Pico
b)
    (MkDiffTime Pico
a) * :: DiffTime -> DiffTime -> DiffTime
* (MkDiffTime Pico
b) = Pico -> DiffTime
MkDiffTime (Pico
a Pico -> Pico -> Pico
forall a. Num a => a -> a -> a
* Pico
b)
    negate :: DiffTime -> DiffTime
negate (MkDiffTime Pico
a) = Pico -> DiffTime
MkDiffTime (Pico -> Pico
forall a. Num a => a -> a
negate Pico
a)
    abs :: DiffTime -> DiffTime
abs (MkDiffTime Pico
a) = Pico -> DiffTime
MkDiffTime (Pico -> Pico
forall a. Num a => a -> a
abs Pico
a)
    signum :: DiffTime -> DiffTime
signum (MkDiffTime Pico
a) = Pico -> DiffTime
MkDiffTime (Pico -> Pico
forall a. Num a => a -> a
signum Pico
a)
    fromInteger :: Integer -> DiffTime
fromInteger Integer
i = Pico -> DiffTime
MkDiffTime (Integer -> Pico
forall a. Num a => Integer -> a
fromInteger Integer
i)

instance Real DiffTime where
    toRational :: DiffTime -> Rational
toRational (MkDiffTime Pico
a) = Pico -> Rational
forall a. Real a => a -> Rational
toRational Pico
a

instance Fractional DiffTime where
    (MkDiffTime Pico
a) / :: DiffTime -> DiffTime -> DiffTime
/ (MkDiffTime Pico
b) = Pico -> DiffTime
MkDiffTime (Pico
a Pico -> Pico -> Pico
forall a. Fractional a => a -> a -> a
/ Pico
b)
    recip :: DiffTime -> DiffTime
recip (MkDiffTime Pico
a) = Pico -> DiffTime
MkDiffTime (Pico -> Pico
forall a. Fractional a => a -> a
recip Pico
a)
    fromRational :: Rational -> DiffTime
fromRational Rational
r = Pico -> DiffTime
MkDiffTime (Rational -> Pico
forall a. Fractional a => Rational -> a
fromRational Rational
r)

instance RealFrac DiffTime where
    properFraction :: forall b. Integral b => DiffTime -> (b, DiffTime)
properFraction (MkDiffTime Pico
a) =
        let
            (b
b', Pico
a') = Pico -> (b, Pico)
forall b. Integral b => Pico -> (b, Pico)
forall a b. (RealFrac a, Integral b) => a -> (b, a)
properFraction Pico
a
        in
            (b
b', Pico -> DiffTime
MkDiffTime Pico
a')
    truncate :: forall b. Integral b => DiffTime -> b
truncate (MkDiffTime Pico
a) = Pico -> b
forall b. Integral b => Pico -> b
forall a b. (RealFrac a, Integral b) => a -> b
truncate Pico
a
    round :: forall b. Integral b => DiffTime -> b
round (MkDiffTime Pico
a) = Pico -> b
forall b. Integral b => Pico -> b
forall a b. (RealFrac a, Integral b) => a -> b
round Pico
a
    ceiling :: forall b. Integral b => DiffTime -> b
ceiling (MkDiffTime Pico
a) = Pico -> b
forall b. Integral b => Pico -> b
forall a b. (RealFrac a, Integral b) => a -> b
ceiling Pico
a
    floor :: forall b. Integral b => DiffTime -> b
floor (MkDiffTime Pico
a) = Pico -> b
forall b. Integral b => Pico -> b
forall a b. (RealFrac a, Integral b) => a -> b
floor Pico
a

-- Let GHC derive the instances when 'Fixed' has 'TH.Lift' instance.
instance TH.Lift DiffTime where
    liftTyped :: TH.Quote m => DiffTime -> TH.Code m DiffTime
    liftTyped :: forall (m :: * -> *). Quote m => DiffTime -> Code m DiffTime
liftTyped (MkDiffTime (MkFixed Integer
a)) = [||Pico -> DiffTime
MkDiffTime (Integer -> Fixed a
forall k (a :: k). Integer -> Fixed a
MkFixed $$(Integer -> Code m Integer
forall t (m :: * -> *). (Lift t, Quote m) => t -> Code m t
forall (m :: * -> *). Quote m => Integer -> Code m Integer
TH.liftTyped Integer
a))||]

-- | Create a 'DiffTime' which represents an integral number of seconds.
secondsToDiffTime :: Integer -> DiffTime
secondsToDiffTime :: Integer -> DiffTime
secondsToDiffTime = Integer -> DiffTime
forall a. Num a => Integer -> a
fromInteger

-- | Create a 'DiffTime' from a number of picoseconds.
picosecondsToDiffTime :: Integer -> DiffTime
picosecondsToDiffTime :: Integer -> DiffTime
picosecondsToDiffTime Integer
x = Pico -> DiffTime
MkDiffTime (Integer -> Pico
forall k (a :: k). Integer -> Fixed a
MkFixed Integer
x)

-- | Get the number of picoseconds in a 'DiffTime'.
diffTimeToPicoseconds :: DiffTime -> Integer
diffTimeToPicoseconds :: DiffTime -> Integer
diffTimeToPicoseconds (MkDiffTime (MkFixed Integer
x)) = Integer
x

{-# RULES
"realToFrac/DiffTime->Pico" realToFrac = \(MkDiffTime ps) -> ps
"realToFrac/Pico->DiffTime" realToFrac = MkDiffTime
    #-}