{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Data.Hourglass.Time
(
Time(..)
, Timeable(..)
, Elapsed(..)
, ElapsedP(..)
, timeConvert
, timeGetDate
, timeGetDateTimeOfDay
, timeGetTimeOfDay
, Duration(..)
, Period(..)
, TimeInterval(..)
, timeAdd
, timeDiff
, timeDiffP
, dateAddPeriod
) where
import Data.Data ()
import Data.Hourglass.Types
import Data.Hourglass.Calendar
import Data.Hourglass.Diff
import Foreign.C.Types (CTime(..))
class Timeable t where
timeGetElapsedP :: t -> ElapsedP
timeGetElapsed :: t -> Elapsed
timeGetElapsed t
t = Elapsed
e where ElapsedP Elapsed
e NanoSeconds
_ = t -> ElapsedP
forall t. Timeable t => t -> ElapsedP
timeGetElapsedP t
t
timeGetNanoSeconds :: t -> NanoSeconds
timeGetNanoSeconds t
t = NanoSeconds
ns where ElapsedP Elapsed
_ NanoSeconds
ns = t -> ElapsedP
forall t. Timeable t => t -> ElapsedP
timeGetElapsedP t
t
class Timeable t => Time t where
timeFromElapsedP :: ElapsedP -> t
timeFromElapsed :: Elapsed -> t
timeFromElapsed Elapsed
e = ElapsedP -> t
forall t. Time t => ElapsedP -> t
timeFromElapsedP (Elapsed -> NanoSeconds -> ElapsedP
ElapsedP Elapsed
e NanoSeconds
0)
#if (MIN_VERSION_base(4,5,0))
instance Timeable CTime where
timeGetElapsedP :: CTime -> ElapsedP
timeGetElapsedP CTime
c = Elapsed -> NanoSeconds -> ElapsedP
ElapsedP (CTime -> Elapsed
forall t. Timeable t => t -> Elapsed
timeGetElapsed CTime
c) NanoSeconds
0
timeGetElapsed :: CTime -> Elapsed
timeGetElapsed (CTime Int64
c) = Seconds -> Elapsed
Elapsed (Int64 -> Seconds
Seconds (Int64 -> Seconds) -> Int64 -> Seconds
forall a b. (a -> b) -> a -> b
$ Int64 -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
c)
timeGetNanoSeconds :: CTime -> NanoSeconds
timeGetNanoSeconds CTime
_ = NanoSeconds
0
instance Time CTime where
timeFromElapsedP :: ElapsedP -> CTime
timeFromElapsedP (ElapsedP Elapsed
e NanoSeconds
_) = Elapsed -> CTime
forall t. Time t => Elapsed -> t
timeFromElapsed Elapsed
e
timeFromElapsed :: Elapsed -> CTime
timeFromElapsed (Elapsed (Seconds Int64
c)) = Int64 -> CTime
CTime (Int64 -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
c)
#endif
instance Timeable Elapsed where
timeGetElapsedP :: Elapsed -> ElapsedP
timeGetElapsedP Elapsed
e = Elapsed -> NanoSeconds -> ElapsedP
ElapsedP Elapsed
e NanoSeconds
0
timeGetElapsed :: Elapsed -> Elapsed
timeGetElapsed Elapsed
e = Elapsed
e
timeGetNanoSeconds :: Elapsed -> NanoSeconds
timeGetNanoSeconds Elapsed
_ = NanoSeconds
0
instance Time Elapsed where
timeFromElapsedP :: ElapsedP -> Elapsed
timeFromElapsedP (ElapsedP Elapsed
e NanoSeconds
_) = Elapsed
e
timeFromElapsed :: Elapsed -> Elapsed
timeFromElapsed Elapsed
e = Elapsed
e
instance Timeable ElapsedP where
timeGetElapsedP :: ElapsedP -> ElapsedP
timeGetElapsedP ElapsedP
e = ElapsedP
e
timeGetNanoSeconds :: ElapsedP -> NanoSeconds
timeGetNanoSeconds (ElapsedP Elapsed
_ NanoSeconds
ns) = NanoSeconds
ns
instance Time ElapsedP where
timeFromElapsedP :: ElapsedP -> ElapsedP
timeFromElapsedP ElapsedP
e = ElapsedP
e
instance Timeable Date where
timeGetElapsedP :: Date -> ElapsedP
timeGetElapsedP Date
d = DateTime -> ElapsedP
forall t. Timeable t => t -> ElapsedP
timeGetElapsedP (Date -> TimeOfDay -> DateTime
DateTime Date
d (Hours -> Minutes -> Seconds -> NanoSeconds -> TimeOfDay
TimeOfDay Hours
0 Minutes
0 Seconds
0 NanoSeconds
0))
instance Time Date where
timeFromElapsedP :: ElapsedP -> Date
timeFromElapsedP (ElapsedP Elapsed
elapsed NanoSeconds
_) = Date
d
where (DateTime Date
d TimeOfDay
_) = Elapsed -> DateTime
dateTimeFromUnixEpoch Elapsed
elapsed
instance Timeable DateTime where
timeGetElapsedP :: DateTime -> ElapsedP
timeGetElapsedP DateTime
d = Elapsed -> NanoSeconds -> ElapsedP
ElapsedP (DateTime -> Elapsed
dateTimeToUnixEpoch DateTime
d) (DateTime -> NanoSeconds
forall t. Timeable t => t -> NanoSeconds
timeGetNanoSeconds DateTime
d)
timeGetElapsed :: DateTime -> Elapsed
timeGetElapsed DateTime
d = DateTime -> Elapsed
dateTimeToUnixEpoch DateTime
d
timeGetNanoSeconds :: DateTime -> NanoSeconds
timeGetNanoSeconds (DateTime Date
_ (TimeOfDay Hours
_ Minutes
_ Seconds
_ NanoSeconds
ns)) = NanoSeconds
ns
instance Time DateTime where
timeFromElapsedP :: ElapsedP -> DateTime
timeFromElapsedP ElapsedP
elapsed = ElapsedP -> DateTime
dateTimeFromUnixEpochP ElapsedP
elapsed
timeConvert :: (Timeable t1, Time t2) => t1 -> t2
timeConvert :: t1 -> t2
timeConvert t1
t1 = ElapsedP -> t2
forall t. Time t => ElapsedP -> t
timeFromElapsedP (t1 -> ElapsedP
forall t. Timeable t => t -> ElapsedP
timeGetElapsedP t1
t1)
{-# INLINE[2] timeConvert #-}
{-# RULES "timeConvert/ID" timeConvert = id #-}
{-# RULES "timeConvert/ElapsedP" timeConvert = timeGetElapsedP #-}
{-# RULES "timeConvert/Elapsed" timeConvert = timeGetElapsed #-}
timeGetDate :: Timeable t => t -> Date
timeGetDate :: t -> Date
timeGetDate t
t = Date
d where (DateTime Date
d TimeOfDay
_) = t -> DateTime
forall t. Timeable t => t -> DateTime
timeGetDateTimeOfDay t
t
{-# INLINE[2] timeGetDate #-}
{-# RULES "timeGetDate/ID" timeGetDate = id #-}
{-# RULES "timeGetDate/DateTime" timeGetDate = dtDate #-}
timeGetTimeOfDay :: Timeable t => t -> TimeOfDay
timeGetTimeOfDay :: t -> TimeOfDay
timeGetTimeOfDay t
t = TimeOfDay
tod where (DateTime Date
_ TimeOfDay
tod) = t -> DateTime
forall t. Timeable t => t -> DateTime
timeGetDateTimeOfDay t
t
{-# INLINE[2] timeGetTimeOfDay #-}
{-# RULES "timeGetTimeOfDay/Date" timeGetTimeOfDay = const (TimeOfDay 0 0 0 0) #-}
{-# RULES "timeGetTimeOfDay/DateTime" timeGetTimeOfDay = dtTime #-}
timeGetDateTimeOfDay :: Timeable t => t -> DateTime
timeGetDateTimeOfDay :: t -> DateTime
timeGetDateTimeOfDay t
t = ElapsedP -> DateTime
dateTimeFromUnixEpochP (ElapsedP -> DateTime) -> ElapsedP -> DateTime
forall a b. (a -> b) -> a -> b
$ t -> ElapsedP
forall t. Timeable t => t -> ElapsedP
timeGetElapsedP t
t
{-# INLINE[2] timeGetDateTimeOfDay #-}
{-# RULES "timeGetDateTimeOfDay/ID" timeGetDateTimeOfDay = id #-}
{-# RULES "timeGetDateTimeOfDay/Date" timeGetDateTimeOfDay = flip DateTime (TimeOfDay 0 0 0 0) #-}
timeAdd :: (Time t, TimeInterval ti) => t -> ti -> t
timeAdd :: t -> ti -> t
timeAdd t
t ti
ti = ElapsedP -> t
forall t. Time t => ElapsedP -> t
timeFromElapsedP (ElapsedP -> t) -> ElapsedP -> t
forall a b. (a -> b) -> a -> b
$ ElapsedP -> Seconds -> ElapsedP
elapsedTimeAddSecondsP (t -> ElapsedP
forall t. Timeable t => t -> ElapsedP
timeGetElapsedP t
t) (ti -> Seconds
forall i. TimeInterval i => i -> Seconds
toSeconds ti
ti)
timeDiff :: (Timeable t1, Timeable t2) => t1 -> t2 -> Seconds
timeDiff :: t1 -> t2 -> Seconds
timeDiff t1
t1 t2
t2 = Seconds
sec where (Elapsed Seconds
sec) = t1 -> Elapsed
forall t. Timeable t => t -> Elapsed
timeGetElapsed t1
t1 Elapsed -> Elapsed -> Elapsed
forall a. Num a => a -> a -> a
- t2 -> Elapsed
forall t. Timeable t => t -> Elapsed
timeGetElapsed t2
t2
timeDiffP :: (Timeable t1, Timeable t2) => t1 -> t2 -> (Seconds, NanoSeconds)
timeDiffP :: t1 -> t2 -> (Seconds, NanoSeconds)
timeDiffP t1
t1 t2
t2 = (Seconds
sec, NanoSeconds
ns)
where (ElapsedP (Elapsed Seconds
sec) NanoSeconds
ns) = t1 -> ElapsedP
forall t. Timeable t => t -> ElapsedP
timeGetElapsedP t1
t1 ElapsedP -> ElapsedP -> ElapsedP
forall a. Num a => a -> a -> a
- t2 -> ElapsedP
forall t. Timeable t => t -> ElapsedP
timeGetElapsedP t2
t2