{-| This is a minimal Haskell library to display duration. @ > let duration = 2 * ms + 3 * oneSecond + 2 * minute + 33*day + 2*year > humanReadableDuration duration "2 years 33 days 2 min 3s 2ms" > getYears duration 2 > getDays duration 763 > getMs duration 65923323002 @ -} module Data.Duration ( humanReadableDuration , humanReadableDuration' , approximativeDuration , Seconds -- durations , ms , oneSecond , minute , hour , day , year -- Retrieve , getMs , getSeconds , getMinutes , getHours , getDays , getYears ) where import Data.Fixed (Fixed (..), Micro, div', mod') type Seconds = Micro {- | `humanReadableDuration` take some time in micro-second precision and render a human readable duration. >>> let duration = 2 * ms + 3 * oneSecond + 2 * minute + 33*day + 2*year >>> duration 65923323.002000 >>> humanReadableDuration duration "2 years 33 days 2 min 3s 2ms" -} humanReadableDuration :: Seconds -> String humanReadableDuration n | n < oneSecond = let mi = getMs n in if mi > 0 then show mi ++ "ms" else "" | n < minute = let s = getSeconds n in if s > 0 then show s ++ "s " ++ humanReadableDuration (n `mod'` oneSecond) else "" | n < hour = let m = getMinutes n in if m > 0 then show m ++ " min " ++ humanReadableDuration (n `mod'` minute) else "" | n < day = let h = getHours n in if h > 0 then show h ++ " hours " ++ humanReadableDuration (n `mod'` hour) else "" | n < year = let d = getDays n in if d > 0 then show d ++ " days " ++ humanReadableDuration (n `mod'` day) else "" | otherwise = let y = getYears n in if y > 0 then show y ++ " years " ++ humanReadableDuration (n `mod'` year) else "" {- | `humanReadableDuration` take some time in micro-second precision and render a human readable duration. >>> let duration = 2 * ms + 3 * oneSecond + 2 * minute + 33*day + 2*year >>> duration 65923323.002000 >>> approximativeDuration duration "2 years" >>> let duration = 2 * ms + 3 * oneSecond + 2 * minute + 33*day >>> approximativeDuration duration "33 days" >>> let duration = 2 * ms + 3 * oneSecond + 280 * minute >>> approximativeDuration duration "4 hours" >>> let duration = 2 * ms + 3 * oneSecond + 22 * minute >>> approximativeDuration duration "22 min" >>> let duration = 2 * ms + 3 * oneSecond >>> approximativeDuration duration "3s" >>> let duration = 12 * ms >>> approximativeDuration duration "12ms" -} approximativeDuration :: Micro -> String approximativeDuration n | n < oneSecond = let mi = getMs n in show mi ++ "ms" | n < minute = let s = getSeconds n in show s ++ "s" | n < hour = let m = getMinutes n in show m ++ " min" | n < day = let h = getHours n in show h ++ " hours" | n < year = let d = getDays n in show d ++ " days" | otherwise = let y = getYears n in show y ++ " years" -- | Wrapper around any `Real` input, which works for `DiffTime` and -- `NominalDiffTime` from the time library, or a `Double` of seconds. -- -- >>> import Data.Time.Clock -- >>> humanReadableDuration' (secondsToDiffTime 10) -- "10s " humanReadableDuration' :: Real a => a -> String humanReadableDuration' = humanReadableDuration . realToFrac -------------------------------------------------------------------------------- -- Durations -------------------------------------------------------------------------------- -- | one millisecond (@0.001@) -- -- >>> ms -- 0.001000 -- >>> 1000 * ms -- 1.000000 ms :: Seconds ms = MkFixed 1000 -- | one second (@1@) -- -- >>> oneSecond / ms -- 1000.000000 -- >>> oneSecond -- 1.000000 oneSecond :: Seconds oneSecond = 1000 * ms -- | number of seconds in one minute -- -- >>> minute / oneSecond -- 60.000000 -- >>> minute / ms -- 60000.000000 minute :: Seconds minute = 60 * oneSecond -- | number of seconds in one hour -- -- >>> hour / minute -- 60.000000 -- >>> hour / oneSecond -- 3600.000000 hour :: Seconds hour = 60 * minute -- | number of seconds in one day -- -- >>> day / hour -- 24.000000 -- >>> day / oneSecond -- 86400.000000 day :: Seconds day = 24 * hour -- | number of seconds in one year -- -- >>> year / day -- 365.000000 year :: Seconds year = 365 * day -------------------------------------------------------------------------------- -- Retrieve some durations -------------------------------------------------------------------------------- -- | number of milli seconds given a duration in micro seconds -- -- >>> getMs 1 -- 1000 -- >>> getMs 1.618033 -- 1618 getMs :: Seconds -> Integer getMs n = n `div'` ms -- | number of seconds given a duration in micro seconds -- -- >>> getSeconds 1 -- 1 -- >>> getSeconds 1.618033 -- 1 getSeconds :: Seconds -> Integer getSeconds n = n `div'` oneSecond -- | number of minutes given a duration in micro seconds -- -- >>> getMinutes 60 -- 1 -- >>> getMinutes 59 -- 0 getMinutes :: Seconds -> Integer getMinutes n = n `div'` minute -- | number of hours given a duration in micro seconds -- -- >>> getHours 3600 -- 1 -- >>> getHours (60 * minute) -- 1 -- >>> getHours (2 * day) -- 48 getHours :: Seconds -> Integer getHours n = n `div'` hour -- | number of days given a duration in micro seconds -- -- >>> getDays (10 * day) -- 10 -- >>> getDays (240 * hour) -- 10 getDays :: Seconds -> Integer getDays n = n `div'` day -- | number of years given a duration in micro seconds -- -- >>> getYears (720 * day) -- 1 -- >>> getYears (740 * day) -- 2 getYears :: Seconds -> Integer getYears n = n `div'` year