time-interval 0.1.0.0 → 0.1.1
raw patch · 4 files changed
+115/−96 lines, 4 filesdep ~time-units
Dependency ranges changed: time-units
Files
- NEWS +0/−23
- NEWS.md +48/−0
- src/Data/Time/Interval.hs +59/−66
- time-interval.cabal +8/−7
− NEWS
@@ -1,23 +0,0 @@-This file lists the user-visible interesting changes between releases. For a-full list of changes to the source, see the ChangeLog.----time-interval 0.1.0.0 -- 2015-09-10-===================================--General, build and documentation changes:--* (This is the first release, so everything is new)--New APIs, features and enhancements:--* (This is the first release, so everything is a new feature)--Bug fixes:--* (This is just the first release)--Dependency changes:--* (This is the first release)
+ NEWS.md view
@@ -0,0 +1,48 @@+This file lists the user-visible interesting changes between releases. For a+full list of changes to the source, see the ChangeLog.++++time-interval 0.1.1 2016-05-30+===================================++General, build and documentation changes:++* Add stack.yaml for building with stack and latest stackage LTS+* Better docs, new usage scenario as the previous one was invalid++New APIs, features and enhancements:++* Several new conversion functions, and `time` is deprecated now+* `TimeInterval` has `Num`, `Integral` and `Real` instances++Bug fixes:++* (None)++Dependency changes:++* (None)++++++time-interval 0.1.0.0 -- 2015-09-10+===================================++General, build and documentation changes:++* (This is the first release, so everything is new)++New APIs, features and enhancements:++* (This is the first release, so everything is a new feature)++Bug fixes:++* (This is just the first release)++Dependency changes:++* (This is the first release)
src/Data/Time/Interval.hs view
@@ -1,6 +1,6 @@ {- This file is part of time-interval. -- - Written in 2015 by fr33domlover <fr33domlover@rel4tion.org>.+ - Written in 2015, 2016 by fr33domlover <fr33domlover@riseup.net>. - - ♡ Copying is an act of love. Please copy, reuse and share. -@@ -13,92 +13,85 @@ - <http://creativecommons.org/publicdomain/zero/1.0/>. -} --- | Suppose you have a program which periodically reloads state and saves some--- logs, and you'd like the intervals for these periodic actions to be--- expressed using time units, and abstract away the internal representation--- until the site of actual use. Your code may look like this:+-- To derive Enum instance for TimeInterval+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++-- | Suppose you have 'Settings' type, and one of its fields specifies an+-- amount of time. Suppose you want to use "Data.Time.Units" for that, because+-- it abstracts away the direct use or 'Int' or 'Integer'. Using 'TimeUnit'+-- directly would require to add the concrete time unit type as a type+-- parameter of 'Settings' (or use GHC type related extensions): ----- > data AppState tr ts = AppState--- > { userName :: String--- > , newMessages :: [String]--- > , reloadInterval :: tr--- > , saveInterval :: ts+-- > data Settings t = Settings+-- > { x :: Int+-- > , y :: Text+-- > , z :: t -- > }--- >--- > type App tr ts = StateT (AppState tr ts) IO--- >--- > setReloadInterval :: TimeUnit t => t -> App ()--- > setReloadInterval new = modify $ \ s -> s { reloadInterval = new }--- >--- > syncStateWithFiles :: (TimeUnit tr, TimeUnit ts) => App tr ts ()--- > syncStateWithFiles = do--- > reloadMicrosec <- liftM toMicroseconds $ gets reloadInterval--- > saveMicrosec <- liftM toMicroseconds $ gets saveInterval--- > {- ... use the values ... -} ----- And usage looks like this:------ > setReloadInterval (5 :: Second)------ So every time you add, change or remove a time field, all your type--- signatures need to be updated and all your @App@ actions, even unrelated to--- those times, are stuck with time type parameters in their type signatures.------ An easy and common approach to avoid all the mess is to store the time as an--- integer, i.e. applying 'toMicroseconds' when setting the value rather than--- when using it. That makes things much easier, but then your type (and your--- API) expose the time directly as a number of microseconds, and people end up--- writing things like @1000 * 1000 * 60 * 5@ to say "5 minuts". It's also an--- internal technical detail there's no reason to expose, and should be--- possible to change without breaking anything - e.g. what if your scheduling--- tool one day moves to a higher precision than microseconds? Your high-level--- API would ideally not let that change float all the way up.------ Here's how things can work when using this library.+-- And any use of @z@ would require to specify the @TimeUnit t =>@ constraint.+-- If you want to add more settings fields later which are time durations,+-- you'll need to add more type variables which may break code which uses the+-- 'Settings' type. ----- > data AppState = AppState--- > { userName :: String--- > , newMessages :: [String]--- > , reloadInterval :: TimeInterval--- > , saveInterval :: TimeInterval+-- > data Settings t1 t2 t3 = Settings+-- > { x :: Int+-- > , y :: Text+-- > , z :: t1+-- > , u :: t2+-- > , v :: t3 -- > }--- >--- > type App = StateT AppState IO--- >--- > setReloadInterval :: TimeUnit t => t -> App ()--- > setReloadInterval new = modify $ \ s -> s { reloadInterval = time new }--- >--- > syncStateWithFiles :: App ()--- > syncStateWithFiles = do--- > reloadMicrosec <- liftM microseconds $ gets reloadInterval--- > saveMicrosec <- liftM microseconds $ gets saveInterval--- > {- ... use the values ... -} ----- And usage looks the same:------ > setReloadInterval (5 :: Second)+-- This package provides something between 'Int' and 'TimeUnit'. A concrete+-- type for specifying time durations, which both hide the integers and avoid+-- the type variables: ----- Also, even if you let the user use the 'time' function in their code, e.g.--- like this:+-- > data Settings = Settings+-- > { x :: Int+-- > , y :: Text+-- > , z :: TimeInterval+-- > , u :: TimeInterval+-- > , v :: TimeInterval+-- > } ----- > setReloadInterval $ time (5 :: Second)+-- There is nothing magical here, this is simply a convenience package for+-- people who encounter this issue in their code. ----- ... you stil get the advantages from both worlds.+-- Note that currently 'TimeInterval' stores time as microseconds internally.+-- This may be a problem if you plan to work with smaller intervals+-- (nanoseconds, picoseconds, etc.). If you have such needs, please contact the+-- maintainer to discuss a solution. module Data.Time.Interval ( TimeInterval ()+ , fromTimeUnit+ , toTimeUnit+ , toMicroUnit , time , microseconds ) where -import Data.Time.Units (TimeUnit (..))+import Data.Time.Units -- | A time duration.-newtype TimeInterval = TimeInterval Integer deriving (Eq, Ord, Show)+newtype TimeInterval = TimeInterval Integer+ deriving (Enum, Eq, Integral, Ord, Num, Real, Show) -- | Convert a time value expressed in a some time unit into a 'TimeInterval'.+fromTimeUnit :: TimeUnit t => t -> TimeInterval+fromTimeUnit = TimeInterval . toMicroseconds++-- | Convert a 'TimeInterval' to a 'TimeUnit' instance.+toTimeUnit :: TimeUnit t => TimeInterval -> t+toTimeUnit = fromMicroseconds . microseconds++-- | Specialized 'toTimeUnit' for converting to 'Microsecond' units.+toMicroUnit :: TimeInterval -> Microsecond+toMicroUnit = toTimeUnit++-- | Deprecated alias of 'fromTimeUnit'. time :: TimeUnit t => t -> TimeInterval-time = TimeInterval . toMicroseconds+time = fromTimeUnit+{-# DEPRECATED time "Use 'fromTimeUnit' instead" #-} -- | Express a 'TimeInterval' in microseconds. microseconds :: TimeInterval -> Integer
time-interval.cabal view
@@ -1,10 +1,11 @@ name: time-interval-version: 0.1.0.0+version: 0.1.1 synopsis: Use a time unit class, but hold a concrete time type. description: Two common ways to represent and hold short time intervals seem to be: . 1. Hold time in microseconds as an 'Int' or 'Integer'+ . 2. Use time units abstraction, e.g. see the time-units package . While the second option is a great abstraction to use in APIs, it works for@@ -30,28 +31,28 @@ you'll probably want this library for short time lengths (at most seconds, minutes, hours). For calendar based and related time functions and types, see the @time@ package.-homepage: http://rel4tion.org/projects/time-interval/-bug-reports: http://rel4tion.org/projects/time-interval/tickets/+homepage: http://hub.darcs.net/fr33domlover/time-interval+bug-reports: mailto:fr33domlover@riseup.net license: PublicDomain license-file: COPYING author: fr33domlover maintainer: fr33domlover@riseup.net copyright: ♡ Copying is an act of love. Please copy, reuse and share.-category: Web+category: Data build-type: Simple-extra-source-files: AUTHORS ChangeLog COPYING INSTALL NEWS README.md+extra-source-files: AUTHORS ChangeLog COPYING INSTALL NEWS.md README.md cabal-version: >=1.10 source-repository head type: darcs- location: http://dev.rel4tion.org/fr33domlover/time-interval+ location: http://hub.darcs.net/fr33domlover/time-interval library exposed-modules: Data.Time.Interval -- other-modules: -- other-extensions: build-depends: base >=4.7 && <5- , time-units >=1+ , time-units hs-source-dirs: src default-language: Haskell2010 ghc-options: -Wall