{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} module Tiempo ( TimeInterval -- * TimeInterval to different units and types , toMicroSeconds , toMilliSeconds , toSeconds , toMinutes , toHours , toDays , toNominalDiffTime -- * Time manipulation , fromTime , fromNow , agoTime , ago -- * Unit functions , 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` () -------------------------------------------------------------------------------- -- | converts the supplied @TimeInterval@ to microseconds toMicroSeconds :: TimeInterval -> Int toMicroSeconds (TimeInterval u v) = timeToMicros u v {-# INLINE toMicroSeconds #-} -- | converts the supplied @TimeInterval@ to milliseconds toMilliSeconds :: TimeInterval -> Double toMilliSeconds (TimeInterval u v) = timeToMillis u v {-# INLINE toMilliSeconds #-} -- | converts the supplied @TimeInterval@ to seconds toSeconds :: TimeInterval -> Double toSeconds (TimeInterval u v) = timeToSeconds u v {-# INLINE toSeconds #-} -- | converts the supplied @TimeInterval@ to minutes toMinutes :: TimeInterval -> Double toMinutes (TimeInterval u v) = timeToMinutes u v {-# INLINE toMinutes #-} -- | converts the supplied @TimeInterval@ to hours toHours :: TimeInterval -> Double toHours (TimeInterval u v) = timeToHours u v {-# INLINE toHours #-} -- | converts the supplied @TimeInterval@ to days toDays :: TimeInterval -> Double toDays (TimeInterval u v) = timeToDays u v {-# INLINE toDays #-} -- | converts the supplied @TimeInterval@ to NominalDiffTime toNominalDiffTime :: TimeInterval -> NominalDiffTime toNominalDiffTime (TimeInterval u v) = realToFrac $ timeToSeconds u v {-# INLINE toNominalDiffTime #-} -------------------------------------------------------------------------------- -- | Adds @TimeInterval@ to @UTCTime@ returning a @UTCTime@ in the -- future fromTime :: TimeInterval -> UTCTime -> UTCTime fromTime interval = addUTCTime (toNominalDiffTime interval) {-# INLINE fromTime #-} -- | Adds @TimeInterval@ to @getCurrentTime@ returning a -- @UTCTime@ in the future fromNow :: TimeInterval -> IO UTCTime fromNow interval = fromTime interval `fmap` getCurrentTime {-# INLINE fromNow #-} -- | Substracts @TimeInterval@ from @UTCTime@ returning a @UTCTime@ in -- the past agoTime :: TimeInterval -> UTCTime -> UTCTime agoTime interval = addUTCTime (realToFrac (-1 * toSeconds interval)) {-# INLINE agoTime #-} -- | Substracts @TimeInterval@ from @getCurrentTime@ returning a -- @UTCTime@ in the past ago :: TimeInterval -> IO UTCTime ago interval = agoTime interval `fmap` getCurrentTime {-# INLINE ago #-} -------------------------------------------------------------------------------- -- | given a number, produces a @TimeInterval@ of microseconds microSeconds :: Int -> TimeInterval microSeconds = TimeInterval Micros {-# INLINE microSeconds #-} -- | given a number, produces a @TimeInterval@ of milliseconds milliSeconds :: Int -> TimeInterval milliSeconds = TimeInterval Millis {-# INLINE milliSeconds #-} -- | given a number, produces a @TimeInterval@ of seconds seconds :: Int -> TimeInterval seconds = TimeInterval Seconds {-# INLINE seconds #-} -- | given a number, produces a @TimeInterval@ of minutes minutes :: Int -> TimeInterval minutes = TimeInterval Minutes {-# INLINE minutes #-} -- | given a number, produces a @TimeInterval@ of hours hours :: Int -> TimeInterval hours = TimeInterval Hours {-# INLINE hours #-} -- | given a number, produces a @TimeInterval@ of days days :: Int -> TimeInterval days = TimeInterval Days {-# INLINE days #-} -------------------------------------------------------------------------------- -- | converts the supplied @TimeUnit@ to microseconds timeToMicros :: TimeUnit -> Int -> Int timeToMicros Micros us = us timeToMicros Millis ms = ms * (10 ^ (3 :: Int)) -- (1000µs == 1ms) 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) {-# INLINE timeToMicros #-} 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) {-# INLINE timeToMillis #-} 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) {-# INLINE timeToSeconds #-} 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) {-# INLINE timeToMinutes #-} 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) {-# INLINE timeToHours #-} 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 {-# INLINE timeToDays #-} -------------------------------------------------------------------------------- hoursPerDay :: Int hoursPerDay = 24 {-# INLINE hoursPerDay #-} minutesPerHour :: Int minutesPerHour = 60 {-# INLINE minutesPerHour #-} secondsPerMinute :: Int secondsPerMinute = 60 {-# INLINE secondsPerMinute #-} milliSecondsPerSecond :: Int milliSecondsPerSecond = 1000 {-# INLINE milliSecondsPerSecond #-} microSecondsPerMillis :: Int microSecondsPerMillis = 1000 {-# INLINE microSecondsPerMillis #-}