module Tiempo
( TimeInterval
, toMicroSeconds
, toMilliSeconds
, toSeconds
, toMinutes
, toHours
, toDays
, toNominalDiffTime
, fromTime
, fromNow
, agoTime
, ago
, microSeconds
, milliSeconds
, seconds
, minutes
, hours
, days ) where
import Control.DeepSeq (NFData (..))
import Data.Time (NominalDiffTime, UTCTime, addUTCTime, getCurrentTime)
import Data.Typeable (Typeable)
import GHC.Generics (Generic)
data TimeUnit
= Days | Hours | Minutes | Seconds | Millis | Micros
deriving (Eq, Show, Typeable, Generic)
instance NFData TimeUnit
data TimeInterval
= TimeInterval !TimeUnit !Int
deriving (Eq, Show, Typeable, Generic)
instance NFData TimeInterval where
rnf (TimeInterval unit n) =
unit `seq` n `seq` ()
toMicroSeconds :: TimeInterval -> Int
toMicroSeconds (TimeInterval u v) = timeToMicros u v
toMilliSeconds :: TimeInterval -> Double
toMilliSeconds (TimeInterval u v) = timeToMillis u v
toSeconds :: TimeInterval -> Double
toSeconds (TimeInterval u v) = timeToSeconds u v
toMinutes :: TimeInterval -> Double
toMinutes (TimeInterval u v) = timeToMinutes u v
toHours :: TimeInterval -> Double
toHours (TimeInterval u v) = timeToHours u v
toDays :: TimeInterval -> Double
toDays (TimeInterval u v) = timeToDays u v
toNominalDiffTime :: TimeInterval -> NominalDiffTime
toNominalDiffTime (TimeInterval u v) = realToFrac $ timeToSeconds u v
fromTime :: TimeInterval -> UTCTime -> UTCTime
fromTime interval = addUTCTime (toNominalDiffTime interval)
fromNow :: TimeInterval -> IO UTCTime
fromNow interval = fromTime interval `fmap` getCurrentTime
agoTime :: TimeInterval -> UTCTime -> UTCTime
agoTime interval = addUTCTime (realToFrac (1 * toSeconds interval))
ago :: TimeInterval -> IO UTCTime
ago interval = agoTime interval `fmap` getCurrentTime
microSeconds :: Int -> TimeInterval
microSeconds = TimeInterval Micros
milliSeconds :: Int -> TimeInterval
milliSeconds = TimeInterval Millis
seconds :: Int -> TimeInterval
seconds = TimeInterval Seconds
minutes :: Int -> TimeInterval
minutes = TimeInterval Minutes
hours :: Int -> TimeInterval
hours = TimeInterval Hours
days :: Int -> TimeInterval
days = TimeInterval Days
timeToMicros :: TimeUnit -> Int -> Int
timeToMicros Micros us = us
timeToMicros Millis ms = ms * (10 ^ (3 :: Int))
timeToMicros Seconds secs = timeToMicros Millis (secs * milliSecondsPerSecond)
timeToMicros Minutes mins = timeToMicros Seconds (mins * secondsPerMinute)
timeToMicros Hours hrs = timeToMicros Minutes (hrs * minutesPerHour)
timeToMicros Days dys = timeToMicros Hours (dys * hoursPerDay)
timeToMillis :: TimeUnit -> Int -> Double
timeToMillis Micros us = fromIntegral us / fromIntegral microSecondsPerMillis
timeToMillis Millis ms = fromIntegral ms
timeToMillis Seconds secs = fromIntegral secs * (10 ^ (3 :: Int))
timeToMillis Minutes mins = timeToMillis Seconds (mins * secondsPerMinute)
timeToMillis Hours hrs = timeToMillis Minutes (hrs * minutesPerHour)
timeToMillis Days dys = timeToMillis Hours (dys * hoursPerDay)
timeToSeconds :: TimeUnit -> Int -> Double
timeToSeconds Micros us =
fromIntegral us / fromIntegral (microSecondsPerMillis * milliSecondsPerSecond)
timeToSeconds Millis ms = fromIntegral ms / fromIntegral milliSecondsPerSecond
timeToSeconds Seconds secs = fromIntegral secs
timeToSeconds Minutes mins = fromIntegral $ mins * secondsPerMinute
timeToSeconds Hours hrs = timeToSeconds Minutes (hrs * minutesPerHour)
timeToSeconds Days dys = timeToSeconds Hours (dys * hoursPerDay)
timeToMinutes :: TimeUnit -> Int -> Double
timeToMinutes Micros us =
fromIntegral us / fromIntegral microsPerHour
where
microsPerHour = product [ microSecondsPerMillis
, milliSecondsPerSecond
, secondsPerMinute ]
timeToMinutes Millis ms = fromIntegral ms / fromIntegral microsPerMin
where
microsPerMin = product [ milliSecondsPerSecond
, secondsPerMinute ]
timeToMinutes Seconds secs = fromIntegral secs / fromIntegral secondsPerMinute
timeToMinutes Minutes mins = fromIntegral mins
timeToMinutes Hours hrs = timeToMinutes Minutes (hrs * minutesPerHour)
timeToMinutes Days dys = timeToMinutes Hours (dys * hoursPerDay)
timeToHours :: TimeUnit -> Int -> Double
timeToHours Micros us = fromIntegral us / fromIntegral microsPerHour
where
microsPerHour = product [ microSecondsPerMillis
, milliSecondsPerSecond
, secondsPerMinute
, minutesPerHour ]
timeToHours Millis ms = fromIntegral ms / fromIntegral millisPerHour
where
millisPerHour = product [ milliSecondsPerSecond
, secondsPerMinute
, minutesPerHour ]
timeToHours Seconds secs =
fromIntegral secs / fromIntegral (secondsPerMinute * minutesPerHour)
timeToHours Minutes mins =
fromIntegral mins / fromIntegral minutesPerHour
timeToHours Hours hrs = fromIntegral hrs
timeToHours Days dys = timeToHours Hours (dys * hoursPerDay)
timeToDays :: TimeUnit -> Int -> Double
timeToDays Micros us = fromIntegral us / fromIntegral microsPerDay
where
microsPerDay = product [ microSecondsPerMillis
, milliSecondsPerSecond
, secondsPerMinute
, minutesPerHour
, hoursPerDay ]
timeToDays Millis ms = fromIntegral ms / fromIntegral millisPerDay
where
millisPerDay = product [ milliSecondsPerSecond
, secondsPerMinute
, minutesPerHour
, hoursPerDay ]
timeToDays Seconds secs = fromIntegral secs / fromIntegral secondsPerDay
where
secondsPerDay = product [ secondsPerMinute
, minutesPerHour
, hoursPerDay ]
timeToDays Minutes mins =
fromIntegral mins / fromIntegral (minutesPerHour * hoursPerDay)
timeToDays Hours hrs = fromIntegral $ hrs * hoursPerDay
timeToDays Days dys = fromIntegral dys
hoursPerDay :: Int
hoursPerDay = 24
minutesPerHour :: Int
minutesPerHour = 60
secondsPerMinute :: Int
secondsPerMinute = 60
milliSecondsPerSecond :: Int
milliSecondsPerSecond = 1000
microSecondsPerMillis :: Int
microSecondsPerMillis = 1000