module Data.UTC ( -- * Introduction -- ** Quick Start -- $quickstart -- ** General Concepts -- *** Handling Exceptions -- $exceptions -- *** Integer vs. Int -- $integerint -- *** Leap Seconds -- $leapseconds -- * Interfaces -- ** Date IsDate(..) -- ** Time , IsTime (..) -- ** Unix Time , IsUnixTime(..) -- ** Epoch , Epoch(..) -- ** Getting (Current) Timestamps , HasUnixTime (..) -- * Generic Date/Time Types -- ** Date , Date -- ** Time , Time -- ** DateTime , DateTime (..) -- ** Local Time , Local (..) -- ** Exception , UtcException (..) -- * Formatting -- ** RFC 3339 -- *** Parsing , Rfc3339Parser(..) -- *** Rendering , Rfc3339Renderer(..) -- ** ISO 8601 -- *** Rendering , Iso8601Renderer(..) ) where import Data.UTC.Class.Epoch import Data.UTC.Class.IsDate import Data.UTC.Class.IsTime import Data.UTC.Class.IsUnixTime import Data.UTC.Class.HasUnixTime import Data.UTC.Type.Date import Data.UTC.Type.Time import Data.UTC.Type.DateTime import Data.UTC.Type.Local import Data.UTC.Type.Exception import Data.UTC.Format.Rfc3339 import Data.UTC.Format.Iso8601 -- $quickstart -- -- Just import the main module and use the 'DateTime' type! -- It supports all functions you'll find below. -- Use 'Maybe' for all occurences of 'm'. -- -- > Prelude> import Data.UTC -- > Prelude Data.UTC> type MT = Maybe (Local DateTime) -- > Prelude Data.UTC> type MS = Maybe String -- > Prelude Data.UTC> (parseRfc3339 "2014-12-24T13:37:00Z" :: MT) >>= addHours 25 >>= setMonth 1 >>= renderRfc3339 :: MS -- > Just "2014-01-25T14:37:00Z" -- $exceptions -- -- The library's main idea is to make it hard to use it wrong. It should -- be impossible by the API's design to construct invalid date or time values. -- -- Furthermore, the library is safe in the sense that its functions don't do -- anything that is not visible in the functions signature. Escpecially, none of the -- functions throw exceptions via 'Prelude.error' or 'Prelude.undefined'. -- -- Whenever a function cannot be total, its result is wrapped in a type variable with -- a 'Monad.Control.MonadThrow' restriction on it which works nicely even in complex -- monad transformer stacks. You can always just use 'Prelude.Maybe' and -- 'Data.Maybe.fromMaybe' to obtain a plain value: -- -- > fromMaybe epoch (addDays 24 epoch) :: Date -- > > 1970-01-25 -- -- Using another 'Monad.Control.MonadThrow' instance might give you additional information in case of failure: -- -- > setHour 10 epoch >>= setMinute 61 :: IO Time -- > > *** Exception: UtcException "Time: setMinute 61 10:00:00" -- > -- > setHour 10 epoch >>= setMinute 61 :: Either Control.Exception.SomeException Time -- > > Left (UtcException "Time: setMinute 61 10:00:00") -- $integerint -- -- This library uses 'Prelude.Integer' instead of 'Prelude.Int'. This bears the advantage -- of easier reasoning about the code's correctness and the ability -- to work on date and time with arbitrary range and precision. -- -- One might think that 'Prelude.Integer' is slower, but indeed it uses 'Prelude.Int' -- internally unless its range is exceeded. The dispatching should not take more than a -- few cycles. Using 'Prelude.Int' in the first place can rightly be considered -- /premature optimisation/. If this really is your application's bottle neck -- you should first consider creating your own time type (i.e. a newtyped 'Prelude.Int' -- representing Unixtime) and making it an instance of the relevant classes. -- Do the critical operations on the bare type. If that is not an option consider -- using a more specialised library. -- $leapseconds -- -- As most other date and time libraries this library does __not support__ handling of leap seconds. -- -- The problem is not so much that this task would be tedious and difficult, but -- rather that future leap seconds are not known in advance and are announced -- just a few weeks before they occur. -- How should a library deal with this? Changing the function's semantic from version to version whenever -- a leap second occured? Probably not desireable. The only sane answer seems to be: /Not at all!/ -- -- In reality the problem is less severe than it seems: Your system clock is most probably -- counting unix seconds and does not know about leap seconds either. So chances are that -- when dealing with computer generated timestamps you'll never encounter problems with -- leap seconds.