packages feed

utc 0.1.0.1 → 0.2.0.0

raw patch · 20 files changed

+506/−255 lines, 20 filesdep +exceptions

Dependencies added: exceptions

Files

Data/UTC.hs view
@@ -6,8 +6,8 @@    -- ** General Concepts -  -- *** Handling Failure-  -- $failure+  -- *** Handling Exceptions+  -- $exceptions    -- *** Integer vs. Int   -- $integerint@@ -22,9 +22,8 @@   , IsTime (..)   -- ** Unix Time   , IsUnixTime(..)-  -- ** Epoch / Midnight+  -- ** Epoch   , Epoch(..)-  , Midnight(..)     -- ** Getting (Current) Timestamps   , HasUnixTime (..)   -- * Generic Date/Time Types@@ -36,6 +35,8 @@   , DateTime (..)   -- ** Local Time   , Local (..)+  -- ** Exception+  , UtcException (..)    -- * Formatting   -- ** RFC 3339@@ -43,10 +44,12 @@   , Rfc3339Parser(..)   -- *** Rendering   , Rfc3339Renderer(..)+  -- ** ISO 8601+  -- *** Rendering+  , Iso8601Renderer(..)   ) where  import Data.UTC.Class.Epoch-import Data.UTC.Class.Midnight import Data.UTC.Class.IsDate import Data.UTC.Class.IsTime import Data.UTC.Class.IsUnixTime@@ -55,7 +58,9 @@ 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 --@@ -63,13 +68,13 @@ -- It supports all functions you'll find below. -- Use 'Maybe' for all occurences of 'm'. ----- > Prelude> :m +Data.UTC+-- > 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" --- $failure+-- $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.@@ -79,16 +84,20 @@ -- 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 'Prelude.Monad' restriction on it. You can always just use 'Prelude.Maybe' and+-- 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+-- > fromMaybe epoch (addDays 24 epoch) :: Date -- > > 1970-01-25 ----- Using another 'Prelude.Monad' instance might give you additional information in case of failure:+-- Using another 'Monad.Control.MonadThrow' instance might give you additional information in case of failure: ----- > setHour 10 midnight >>= setMinute 61 :: IO Time--- > > *** Exception: user error (Time.setMinute 61)+-- > 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 --
Data/UTC/Class.hs view
@@ -4,11 +4,9 @@   , module Data.UTC.Class.IsUnixTime   , module Data.UTC.Class.HasUnixTime   , module Data.UTC.Class.Epoch-  , module Data.UTC.Class.Midnight   ) where  import Data.UTC.Class.Epoch-import Data.UTC.Class.Midnight import Data.UTC.Class.IsDate import Data.UTC.Class.IsTime import Data.UTC.Class.IsUnixTime
Data/UTC/Class/HasUnixTime.hs view
@@ -1,10 +1,13 @@ {-# LANGUAGE Safe #-} module Data.UTC.Class.HasUnixTime where +import Control.Monad.Catch+ import Data.Ratio import System.Clock as C  import Data.UTC.Class.IsUnixTime+import Data.UTC.Type.Exception  -- | This class defines an interface for contexts that can be asked for a timestamp. --@@ -40,5 +43,5 @@     = do TimeSpec s ns <- C.getTime Realtime          case fromUnixSeconds ((fromIntegral s) % 1 + (fromIntegral ns) % 1000000000) of            Just t  -> return t-           Nothing -> fail "Data.UTC.Class.HasUnixTime.getUnixTime: failed"+           Nothing -> throwM $ UtcException "HasUnixTime IO: getUnixTime" 
Data/UTC/Class/IsDate.hs view
@@ -3,6 +3,8 @@   ( IsDate (..)   ) where +import Control.Monad.Catch+ import Data.UTC.Internal import Data.UTC.Class.Epoch @@ -34,15 +36,15 @@   -- > > Just 2005-02-28   -- > setYear 2005 "2004-02-29" :: Maybe Date   -- > > Nothing-  setYear               :: (Monad m) => Integer  -> t -> m t+  setYear               :: (MonadThrow m) => Integer  -> t -> m t   -- | Sets the month of year and fails if the result would be invalid.   --   -- The function only accepts input ranging from 1 to 12.-  setMonth              :: (Monad m) => Integer  -> t -> m t+  setMonth              :: (MonadThrow m) => Integer  -> t -> m t   -- | Sets the day of month and fails if the result would be invalid.   --   -- The function only accepts input ranging from 1 to 31 (or less depending on month and year).-  setDay                :: (Monad m) => Integer  -> t -> m t+  setDay                :: (MonadThrow m) => Integer  -> t -> m t    -- | A /year/ is a relative amount of time.   -- The function's semantic is a follows:@@ -57,7 +59,7 @@   -- > > Just 2004-02-29   -- > addYears 1 "2000-02-29" :: Maybe Date   -- > > Just 2001-02-28-  addYears              :: (Monad m) => Integer  -> t -> m t+  addYears              :: (MonadThrow m) => Integer  -> t -> m t   addYears ys t     = if isValidDate (year t + ys, month t, day t)         then setYear (year t + ys) t@@ -72,7 +74,7 @@   --   -- > addMonths (-13) "1970-01-01" :: Maybe Date   -- > > Just 1968-12-01-  addMonths             :: (Monad m) => Integer  -> t -> m t+  addMonths             :: (MonadThrow m) => Integer  -> t -> m t   addMonths ms t     = setDay 1 t >>= setYear y >>= setMonth m >>= setDay d     where@@ -97,7 +99,7 @@   -- > > Just 1971-01-01   -- > addDays 365 "2000-01-01" :: Maybe Date   -- > > Just 2000-12-31-  addDays               :: (Monad m) => Integer  -> t -> m t+  addDays               :: (MonadThrow m) => Integer  -> t -> m t   addDays ds t     -- setDay 1 to avoid intermediate generation of invalid dates!     = setDay 1 t >>= setYear y >>= setMonth m >>= setDay d
Data/UTC/Class/IsTime.hs view
@@ -3,6 +3,8 @@   ( IsTime (..)   ) where +import Control.Monad.Catch+ import Data.Ratio  import Data.UTC.Internal@@ -21,26 +23,26 @@   -- | Accepts values in the range 0 to 23.   --   -- The function fails if the result cannot be represented by the type (cannot happen for 'Data.UTC.Time' and 'Data.UTC.DateTime').-  setHour               :: (Monad m) => Integer  -> t -> m t+  setHour               :: (MonadThrow m) => Integer  -> t -> m t   -- | Accepts values in the range 0 to 59.   --   -- The function fails if the result cannot be represented by the type (cannot happen for 'Data.UTC.Time' and 'Data.UTC.DateTime').-  setMinute             :: (Monad m) => Integer  -> t -> m t+  setMinute             :: (MonadThrow m) => Integer  -> t -> m t   -- | Accepts values in the range 0 to 59.   --   -- The function fails if the result cannot be represented by the type (cannot happen for 'Data.UTC.Time' and 'Data.UTC.DateTime').-  setSecond             :: (Monad m) => Integer  -> t -> m t+  setSecond             :: (MonadThrow m) => Integer  -> t -> m t   -- | Accepts values in the range 0.0 <= x < 1.0.   --   -- The function fails if the result cannot be represented by the type (cannot happen for 'Data.UTC.Time' and 'Data.UTC.DateTime').-  setSecondFraction     :: (Monad m) => Rational -> t -> m t+  setSecondFraction     :: (MonadThrow m) => Rational -> t -> m t    -- | Adds an arbitrary count of hours (positive or negative).   --   --   * Full days flow over to 'Data.UTC.addDays' if the type is also an instance of 'Data.UTC.Class.IsDate' (this is the case for 'Data.UTC.DateTime').   --   * Types not implementing the 'Data.UTC.Class.IsDate' class should just ignore the days part on overflow (like 'Data.UTC.Time' does).   --   * Fails if the result cannot be represented by the type (cannot happen for 'Data.UTC.Time' and 'Data.UTC.DateTime').-  addHours              :: (Monad m) => Integer  -> t -> m t+  addHours              :: (MonadThrow m) => Integer  -> t -> m t   addHours h t     = setHour hors t     where@@ -51,7 +53,7 @@   --   --   * Full hours flow over to 'addHours'.   --   * Fails if the result cannot be represented by the type (cannot happen for 'Data.UTC.Time' and 'Data.UTC.DateTime').-  addMinutes            :: (Monad m) => Integer  -> t -> m t+  addMinutes            :: (MonadThrow m) => Integer  -> t -> m t   addMinutes m t     = setMinute mins t >>= addHours hors     where@@ -63,7 +65,7 @@   --   --   * Full minutes flow over to 'addMinutes'.   --   * Fails if the result cannot be represented by the type (cannot happen for 'Data.UTC.Time' and 'Data.UTC.DateTime').-  addSeconds            :: (Monad m) => Integer  -> t -> m t+  addSeconds            :: (MonadThrow m) => Integer  -> t -> m t   addSeconds s t     = setSecond secs t >>= addMinutes mins     where@@ -76,7 +78,7 @@   --   * Full seconds flow over to 'addSeconds'.   --   * Instances of this class are not required to preserve full precision (although 'Data.UTC.Time' and 'Data.UTC.DateTime' do so).   --   * Fails if the result cannot be represented by the type (cannot happen for 'Data.UTC.Time' and 'Data.UTC.DateTime').-  addSecondFractions    :: (Monad m) => Rational -> t -> m t+  addSecondFractions    :: (MonadThrow m) => Rational -> t -> m t   addSecondFractions f t     | f == 0    = return t     | f >= 0    = setSecondFraction frcs t         >>= addSeconds secs
Data/UTC/Class/IsUnixTime.hs view
@@ -3,6 +3,8 @@   ( IsUnixTime(..)   ) where +import Control.Monad.Catch+ -- | This class is for types that have a well-defined -- mapping to and from the <https://en.wikipedia.org/wiki/Unix_time Unix Time> system  -- (based on <https://en.wikipedia.org/wiki/Coordinated_Universal_Time UTC>).@@ -18,4 +20,4 @@ -- The concrete behaviour of your system clock is implementation dependant. class IsUnixTime t where   unixSeconds      :: t -> Rational-  fromUnixSeconds  :: Monad m => Rational -> m t+  fromUnixSeconds  :: MonadThrow m => Rational -> m t
− Data/UTC/Class/Midnight.hs
@@ -1,9 +0,0 @@-{-# LANGUAGE Safe #-}-module Data.UTC.Class.Midnight-  ( Midnight(..)-  ) where---- | The beginning of a day: 00:00:00-class Midnight t where-  midnight :: t-
+ Data/UTC/Format/Iso8601.hs view
@@ -0,0 +1,198 @@+{-# LANGUAGE FlexibleInstances #-}+module Data.UTC.Format.Iso8601 where++import Control.Monad.Catch++import Data.Monoid+import qualified Data.ByteString            as BS+import qualified Data.ByteString.Builder    as BS+import qualified Data.ByteString.Lazy       as BSL+import qualified Data.Text                  as T+import qualified Data.Text.Encoding         as T+import qualified Data.Text.Lazy             as TL+import qualified Data.Text.Lazy.Encoding    as TL++import Data.UTC.Class.IsDate+import Data.UTC.Class.IsTime+import Data.UTC.Type.Exception++class Iso8601Renderer string where+  -- | __YYYYMMDD__+  renderIso8601CalendarDate  :: (MonadThrow m, IsDate t) => t -> m string+  -- | __YYYY-MM-DD__ (extended format)+  renderIso8601CalendarDate' :: (MonadThrow m, IsDate t) => t -> m string++  -- | __hhmmss__+  renderIso8601TimeHms       :: (MonadThrow m, IsTime t) => t -> m string+  -- | __hh:mm:ss__ (extended format)+  renderIso8601TimeHms'      :: (MonadThrow m, IsTime t) => t -> m string+  -- | __hhmm__+  renderIso8601TimeHm        :: (MonadThrow m, IsTime t) => t -> m string+  -- | __hh:mm__ (extended format)+  renderIso8601TimeHm'       :: (MonadThrow m, IsTime t) => t -> m string++instance Iso8601Renderer BS.ByteString where+  renderIso8601CalendarDate t+    = renderIso8601CalendarDate     t >>= return . BSL.toStrict+  renderIso8601CalendarDate' t+    = renderIso8601CalendarDate'    t >>= return . BSL.toStrict+  renderIso8601TimeHms t+    = renderIso8601TimeHms          t >>= return . BSL.toStrict+  renderIso8601TimeHms' t+    = renderIso8601TimeHms'         t >>= return . BSL.toStrict+  renderIso8601TimeHm t+    = renderIso8601TimeHm           t >>= return . BSL.toStrict+  renderIso8601TimeHm' t+    = renderIso8601TimeHm'          t >>= return . BSL.toStrict++instance Iso8601Renderer T.Text where+  renderIso8601CalendarDate t+    = renderIso8601CalendarDate     t >>= return . T.decodeUtf8+  renderIso8601CalendarDate' t+    = renderIso8601CalendarDate'    t >>= return . T.decodeUtf8+  renderIso8601TimeHms t+    = renderIso8601TimeHms          t >>= return . T.decodeUtf8+  renderIso8601TimeHms' t+    = renderIso8601TimeHms'         t >>= return . T.decodeUtf8+  renderIso8601TimeHm t+    = renderIso8601TimeHm           t >>= return . T.decodeUtf8+  renderIso8601TimeHm' t+    = renderIso8601TimeHm'          t >>= return . T.decodeUtf8++instance Iso8601Renderer TL.Text where+  renderIso8601CalendarDate t+    = renderIso8601CalendarDate     t >>= return . TL.decodeUtf8+  renderIso8601CalendarDate' t+    = renderIso8601CalendarDate'    t >>= return . TL.decodeUtf8+  renderIso8601TimeHms t+    = renderIso8601TimeHms          t >>= return . TL.decodeUtf8+  renderIso8601TimeHms' t+    = renderIso8601TimeHms'         t >>= return . TL.decodeUtf8+  renderIso8601TimeHm t+    = renderIso8601TimeHm           t >>= return . TL.decodeUtf8+  renderIso8601TimeHm' t+    = renderIso8601TimeHm'          t >>= return . TL.decodeUtf8++instance Iso8601Renderer [Char] where+  renderIso8601CalendarDate t +    = renderIso8601CalendarDate     t >>= return . T.unpack+  renderIso8601CalendarDate' t +    = renderIso8601CalendarDate'    t >>= return . T.unpack+  renderIso8601TimeHms t+    = renderIso8601TimeHms          t >>= return . T.unpack+  renderIso8601TimeHms' t+    = renderIso8601TimeHms'         t >>= return . T.unpack+  renderIso8601TimeHm t+    = renderIso8601TimeHm           t >>= return . T.unpack+  renderIso8601TimeHm' t+    = renderIso8601TimeHm'          t >>= return . T.unpack++instance Iso8601Renderer BSL.ByteString where+  renderIso8601CalendarDate t+    | 0 <= yyyy && yyyy <= 9999+    = return+    $ BS.toLazyByteString+    $ mconcat+        [ BS.word16HexFixed (y3*16*16*16 + y2*16*16 + y1*16 + y0)+        , BS.word8HexFixed (m1*16 + m0)+        , BS.word8HexFixed (d1*16 + d0)+        ]+    | otherwise+    = throwM $ UtcException $ "Iso8601: renderIso8601CalendarDate (year " ++ show yyyy ++ " out of range 0-9999)"+    where+      yyyy = year  t+      mm   = month t+      dd   = day   t+      y3   = fromIntegral $ yyyy  `div` 1000 `mod` 10+      y2   = fromIntegral $ yyyy  `div` 100  `mod` 10+      y1   = fromIntegral $ yyyy  `div` 10   `mod` 10+      y0   = fromIntegral $ yyyy  `div` 1    `mod` 10+      m1   = fromIntegral $ mm    `div` 10   `mod` 10+      m0   = fromIntegral $ mm    `div` 1    `mod` 10+      d1   = fromIntegral $ dd    `div` 10   `mod` 10+      d0   = fromIntegral $ dd    `div` 1    `mod` 10++  renderIso8601CalendarDate' t+    | 0 <= yyyy && yyyy <= 9999+    = return+    $ BS.toLazyByteString+    $ mconcat+        [ BS.word16HexFixed (y3*16*16*16 + y2*16*16 + y1*16 + y0)+        , BS.char7 '-'+        , BS.word8HexFixed (m1*16 + m0)+        , BS.char7 '-'+        , BS.word8HexFixed (d1*16 + d0)+        ]+    | otherwise+    = throwM $ UtcException $ "Iso8601: renderIso8601CalendarDate (year " ++ show yyyy ++ " out of range 0-9999)"+    where+      yyyy = year  t+      mm   = month t+      dd   = day   t+      y3   = fromIntegral $ yyyy  `div` 1000 `mod` 10+      y2   = fromIntegral $ yyyy  `div` 100  `mod` 10+      y1   = fromIntegral $ yyyy  `div` 10   `mod` 10+      y0   = fromIntegral $ yyyy  `div` 1    `mod` 10+      m1   = fromIntegral $ mm    `div` 10   `mod` 10+      m0   = fromIntegral $ mm    `div` 1    `mod` 10+      d1   = fromIntegral $ dd    `div` 10   `mod` 10+      d0   = fromIntegral $ dd    `div` 1    `mod` 10++  renderIso8601TimeHms t+    = return+    $ BS.toLazyByteString+    $ mconcat+        [ BS.word8HexFixed (h1*16 + h0)+        , BS.word8HexFixed (m1*16 + m0)+        , BS.word8HexFixed (s1*16 + s0)+        ]+    where+      (h1,h0,m1,m0,s1,s0) = timeDigits t++  renderIso8601TimeHms' t+    = return+    $ BS.toLazyByteString+    $ mconcat+        [ BS.word8HexFixed (h1*16 + h0)+        , BS.char7 '-'+        , BS.word8HexFixed (m1*16 + m0)+        , BS.char7 '-'+        , BS.word8HexFixed (s1*16 + s0)+        ]+    where+      (h1,h0,m1,m0,s1,s0) = timeDigits t++  renderIso8601TimeHm t+    = return+    $ BS.toLazyByteString+    $ mconcat+        [ BS.word8HexFixed (h1*16 + h0)+        , BS.word8HexFixed (m1*16 + m0)+        ]+    where+      (h1,h0,m1,m0,_,_) = timeDigits t++  renderIso8601TimeHm' t+    = return+    $ BS.toLazyByteString+    $ mconcat+        [ BS.word8HexFixed (h1*16 + h0)+        , BS.char7 '-'+        , BS.word8HexFixed (m1*16 + m0)+        ]+    where+      (h1,h0,m1,m0,_,_) = timeDigits t++timeDigits t+  = (h1,h0,m1,m0,s1,s0)+  where+    hh   = hour   t+    mm   = minute t+    ss   = second t+    h1   = fromIntegral $ hh `div` 10   `mod` 10+    h0   = fromIntegral $ hh `div` 1    `mod` 10+    m1   = fromIntegral $ mm `div` 10   `mod` 10+    m0   = fromIntegral $ mm `div` 1    `mod` 10+    s1   = fromIntegral $ ss `div` 10   `mod` 10+    s0   = fromIntegral $ ss `div` 1    `mod` 10+
Data/UTC/Format/Rfc3339.hs view
@@ -8,6 +8,8 @@   , rfc3339Parser, rfc3339Builder   ) where +import Control.Monad.Catch+ import qualified Data.Attoparsec.ByteString as Atto import qualified Data.ByteString            as BS import qualified Data.ByteString.Lazy       as BSL@@ -21,17 +23,18 @@ import Data.UTC.Class.IsDate import Data.UTC.Class.IsTime import Data.UTC.Type.Local+import Data.UTC.Type.Exception import Data.UTC.Format.Rfc3339.Parser import Data.UTC.Format.Rfc3339.Builder  class Rfc3339Parser a where-  parseRfc3339 :: (Monad m, IsDate t, IsTime t, Epoch t) => a -> m (Local t)+  parseRfc3339 :: (MonadThrow m, IsDate t, IsTime t, Epoch t) => a -> m (Local t)  instance Rfc3339Parser BS.ByteString where   parseRfc3339 s     = case Atto.parseOnly rfc3339Parser s of-        Right t -> return t-        Left  _ -> fail ""+        Right t -> t+        Left  _ -> throwM $ UtcException $ "Rfc3339Parser: parseRfc3339 " ++ show s  instance Rfc3339Parser BSL.ByteString where   parseRfc3339 s@@ -49,9 +52,16 @@   parseRfc3339 s     = parseRfc3339 (T.pack s) --class Rfc3339Renderer a where-  renderRfc3339 :: (Monad m, IsDate t, IsTime t, Epoch t) => Local t -> m a+-- | > setYear 1987 (epoch :: DateTime) +--   >   >>= setMonth 7 +--   >   >>= setDay 10 +--   >   >>= setHour 12 +--   >   >>= setMinute 4 +--   >   >>= return . (flip Local) (Just 0) +--   >   >>= renderRfc3339 :: Maybe String+--   > > Just "1987-07-10T12:04:00Z"+class Rfc3339Renderer string where+  renderRfc3339 :: (MonadThrow m, IsDate t, IsTime t, Epoch t) => Local t -> m string  instance Rfc3339Renderer BS.ByteString where   renderRfc3339 t
Data/UTC/Format/Rfc3339/Builder.hs view
@@ -11,7 +11,7 @@ import Data.UTC.Class.IsTime  rfc3339Builder :: (Monad m, IsDate t, IsTime t) => Local t -> m BS.Builder-rfc3339Builder (Local t os)+rfc3339Builder (Local os t)   = do -- calculate the single digits        let y3 = fromIntegral $ year t   `div` 1000 `mod` 10            y2 = fromIntegral $ year t   `div` 100  `mod` 10
Data/UTC/Format/Rfc3339/Parser.hs view
@@ -2,6 +2,8 @@   ( rfc3339Parser   ) where +import Control.Monad.Catch+ import Data.Ratio  import Data.Attoparsec.ByteString ( Parser, skipWhile, choice, option, satisfy )@@ -12,7 +14,7 @@ import Data.UTC.Class.IsTime import Data.UTC.Type.Local -rfc3339Parser :: (IsDate t, IsTime t) => Parser (Local t)+rfc3339Parser :: (MonadThrow m, IsDate t, IsTime t) => Parser (m (Local t)) rfc3339Parser    = do year'    <- dateFullYear        _        <- char '-'@@ -27,15 +29,15 @@        second'  <- timeSecond        secfrac' <- option 0 timeSecfrac        offset'  <- timeOffset-       datetime <- return epoch-            >>= setYear                year'-            >>= setMonth               month'-            >>= setDay                 day'-            >>= setHour                hour'-            >>= setMinute              minute'-            >>= setSecond              second'-            >>= setSecondFraction      secfrac'-       return (Local datetime offset')++       return $ do datetime <- setYear           year' epoch+                           >>= setMonth          month'+                           >>= setDay            day'+                           >>= setHour           hour'+                           >>= setMinute         minute'+                           >>= setSecond         second'+                           >>= setSecondFraction secfrac'+                   return (Local offset' datetime)   where     dateFullYear       = decimal4
Data/UTC/Internal.hs view
@@ -11,8 +11,13 @@    , secsPerDay, secsPerHour, secsPerMinute, minsPerHour, hoursPerDay   , monthsPerYear++  , fixedDecimal+  , decimalFraction   ) where +import Data.Ratio+ deltaUnixEpochCommonEpoch :: Rational deltaUnixEpochCommonEpoch   = 62167219200@@ -160,3 +165,28 @@       | otherwise                   = False     isLeapYear       = (y `mod` 4 == 0) && ((y `mod` 400 == 0) || (y `mod` 100 /= 0))++fixedDecimal :: Integer -> Integer -> String+fixedDecimal digits i+  = f digits i []+  where+    f n i accum | n <= 0    = accum+                | otherwise = f (n - 1) (i `div` 10)+                                ((toEnum $ fromIntegral $ 48 + i `mod` 10):accum)++decimalFraction :: Integer -> Rational -> String+decimalFraction _     0+  = ""+decimalFraction limit r+  = '.':(df limit r)+  where+    df limit 0+      = ""+    df 0 _+      = "..."+    df limit r+      = ch:(df (limit - 1) r')+      where+        r10 = r * 10+        ch  = toEnum $ fromIntegral $ 48 + (truncate $ r10) `mod` 10+        r' = r10 - (truncate r10 % 1)
Data/UTC/Type.hs view
@@ -3,9 +3,12 @@   , module Data.UTC.Type.Time   , module Data.UTC.Type.DateTime   , module Data.UTC.Type.Local+  , module Data.UTC.Type.Exception   ) where  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
Data/UTC/Type/Date.hs view
@@ -2,12 +2,15 @@   ( Date ()   ) where +import Control.Monad.Catch+ import Data.Ratio  import Data.UTC.Class.Epoch import Data.UTC.Class.IsDate import Data.UTC.Class.IsUnixTime import Data.UTC.Internal+import Data.UTC.Type.Exception  -- | This type represents dates in the __Proleptic Gregorian Calendar__. --@@ -17,13 +20,31 @@ --     Use 'Data.UTC.epoch' or a parser to construct values. --   * The instance of 'Prelude.Show' is only meant for debugging purposes --     and is subject to change.+--+-- > > show (epoch :: Date)+-- > 1970-01-01 data Date    = Date      { dYear           :: Integer      , dMonth          :: Integer      , dDay            :: Integer-     } deriving (Eq, Ord, Show)+     } deriving (Eq, Ord) +instance Show Date where+  show (Date yy mm dd)+    = concat+        [ if yy < 0+            then "-"+            else ""+        , if abs yy > 9999+            then show (abs yy)+            else fixedDecimal 4 (abs yy)+        , "-"+        , fixedDecimal 2 mm+        , "-"+        , fixedDecimal 2 dd+        ]+ instance Epoch Date where   epoch     = Date@@ -59,13 +80,13 @@   setYear x t     = if isValidDate (x, month t, day t)       then return $ t { dYear  = x }-      else fail   $ "Dated.setYear "  ++ show x+      else throwM $ UtcException $ "IsDate Date: setYear "  ++ show x ++ " " ++ show t   setMonth x t     = if isValidDate (year t, x, day t)       then return $ t { dMonth = x }-      else fail   $ "Dated.setMonth " ++ show x+      else throwM $ UtcException $ "IsDate Date: setMonth " ++ show x ++ " " ++ show t   setDay x t     = if isValidDate (year t, month t, x)       then return $ t { dDay   = x }-      else fail   $ "Dated.setDay "   ++ show x+      else throwM $ UtcException $ "IsDate Date: setDay "   ++ show x ++ " " ++ show t 
Data/UTC/Type/DateTime.hs view
@@ -4,7 +4,6 @@     DateTime (..)   ) where -import Data.String import Data.Maybe  import Data.UTC.Class.Epoch@@ -14,7 +13,6 @@ import Data.UTC.Type.Date import Data.UTC.Type.Time import Data.UTC.Type.Local-import Data.UTC.Format.Rfc3339 import Data.UTC.Internal  -- | A time representation based on a 'Data.UTC.Date' and the 'Data.UTC.Time' of the day.@@ -22,9 +20,11 @@ --   * The type uses multiprecision integers internally and is able to represent --     any UTC date in the past and in the future with arbitrary precision --     (apart from the time span within a leap second).---   * The instances of 'Data.String.IsString' and 'Prelude.Show' are only---     meant for debugging purposes and default to 'epoch' in case of---     failure. Don't rely on their behaviour!+--   * The instance of 'Prelude.Show' is only+--     meant for debugging purposes. Don't rely on its behaviour!+--+-- > > show (epoch :: DateTime)+-- > 1970-01-01T00:00:00 data DateTime    = DateTime      { date  :: Date@@ -32,16 +32,11 @@      } deriving (Eq, Ord)  instance Show DateTime where-  show = fromMaybe "1970-01-01T00:00:00-00:00" . renderRfc3339 . unknown--instance Show (Local DateTime) where-  show = fromMaybe "1970-01-01T00:00:00-00:00" . renderRfc3339--instance IsString DateTime where-  fromString = utc . fromMaybe epoch . parseRfc3339+  show (DateTime d t)+    = show d ++ "T" ++ show t  instance Epoch DateTime where-  epoch = DateTime epoch midnight+  epoch = DateTime epoch epoch  instance IsUnixTime DateTime where   unixSeconds (DateTime d t)@@ -102,121 +97,100 @@  -- assumption: addSecondFractions for DateTime is always successful instance IsDate (Local DateTime) where-  year (Local t Nothing)+  year (Local Nothing t)     = year t-  year (Local t (Just 0))+  year (Local (Just 0) t)     = year t-  year (Local t (Just o))+  year (Local (Just o) t)     = year     $ fromMaybe undefined $ addSecondFractions o t-  month (Local t Nothing)+  month (Local Nothing t)     = month t-  month (Local t (Just 0))+  month (Local (Just 0) t)     = month t-  month (Local t (Just o))+  month (Local (Just o) t)     = month     $ fromMaybe undefined $ addSecondFractions o t-  day (Local t Nothing)+  day (Local Nothing t)     = day t-  day (Local t (Just 0))+  day (Local (Just 0) t)     = day t-  day  (Local t (Just o))+  day  (Local (Just o) t)     = day     $ fromMaybe undefined $ addSecondFractions o t-  setYear h (Local t o@Nothing)-    = do t' <- setYear h t-         return (Local t' o)-  setYear h (Local t o@(Just 0))-    = do t' <- setYear h t-         return (Local t' o)-  setYear h (Local t o@(Just i))-    = do t' <- addSecondFractions i t >>= setYear h >>= addSecondFractions (negate i)-         return (Local t' o)-  setMonth h (Local t o@Nothing)-    = do t' <- setMonth h t-         return (Local t' o)-  setMonth h (Local t o@(Just 0))-    = do t' <- setMonth h t-         return (Local t' o)-  setMonth h (Local t o@(Just i))-    = do t' <- addSecondFractions i t >>= setMonth h >>= addSecondFractions (negate i)-         return (Local t' o)-  setDay h (Local t o@Nothing)-    = do t' <- setDay h t-         return (Local t' o)-  setDay h (Local t o@(Just 0))-    = do t' <- setDay h t-         return (Local t' o)-  setDay h (Local t o@(Just i))-    = do t' <- addSecondFractions i t >>= setDay h >>= addSecondFractions (negate i)-         return (Local t' o)+  setYear h (Local o@Nothing t)+    = Local o <$> setYear h t+  setYear h (Local o@(Just 0) t)+    = Local o <$> setYear h t+  setYear h (Local o@(Just i) t)+    = Local o <$> ( addSecondFractions i t >>= setYear h >>= addSecondFractions (negate i) )+  setMonth h (Local o@Nothing t)+    = Local o <$> setMonth h t+  setMonth h (Local o@(Just 0) t)+    = Local o <$> setMonth h t+  setMonth h (Local o@(Just i) t)+    = Local o <$> ( addSecondFractions i t >>= setMonth h >>= addSecondFractions (negate i) )+  setDay h (Local o@Nothing t)+    = Local o <$> setDay h t+  setDay h (Local o@(Just 0) t)+    = Local o <$> setDay h t+  setDay h (Local o@(Just i) t)+    = Local o <$> ( addSecondFractions i t >>= setDay h >>= addSecondFractions (negate i) )  -- assumption: addSecondFractions for DateTime is always successful instance IsTime (Local DateTime) where-  hour (Local t Nothing)+  hour (Local Nothing t)     = hour t-  hour (Local t (Just 0))+  hour (Local (Just 0) t)     = hour t-  hour (Local t (Just o))+  hour (Local (Just o) t)     = hour     $ fromMaybe undefined $ addSecondFractions o t-  minute (Local t Nothing)+  minute (Local Nothing t)     = minute t-  minute (Local t (Just 0))+  minute (Local (Just 0) t)     = minute t-  minute (Local t (Just o))+  minute (Local (Just o) t)     = minute     $ fromMaybe undefined $ addSecondFractions o t-  second (Local t Nothing)+  second (Local Nothing t)     = second t-  second (Local t (Just 0))+  second (Local (Just 0) t)     = second t-  second  (Local t (Just o))+  second  (Local (Just o) t)     = second     $ fromMaybe undefined $ addSecondFractions o t-  secondFraction (Local t Nothing)+  secondFraction (Local Nothing t)     = secondFraction t-  secondFraction (Local t (Just 0))+  secondFraction (Local (Just 0) t)     = secondFraction t-  secondFraction (Local t (Just o))+  secondFraction (Local (Just o) t)     = secondFraction     $ fromMaybe undefined $ addSecondFractions o t-  setHour h (Local t o@Nothing)-    = do t' <- setHour h t-         return (Local t' o)-  setHour h (Local t o@(Just 0))-    = do t' <- setHour h t-         return (Local t' o)-  setHour h (Local t o@(Just i))-    = do t' <- addSecondFractions i t >>= setHour h >>= addSecondFractions (negate i)-         return (Local t' o)-  setMinute h (Local t o@Nothing)-    = do t' <- setMinute h t-         return (Local t' o)-  setMinute h (Local t o@(Just 0))-    = do t' <- setMinute h t-         return (Local t' o)-  setMinute h (Local t o@(Just i))-    = do t' <- addSecondFractions i t >>= setMinute h >>= addSecondFractions (negate i)-         return (Local t' o)-  setSecond h (Local t o@Nothing)-    = do t' <- setSecond h t-         return (Local t' o)-  setSecond h (Local t o@(Just 0))-    = do t' <- setSecond h t-         return (Local t' o)-  setSecond h (Local t o@(Just i))-    = do t' <- addSecondFractions i t >>= setSecond h >>= addSecondFractions (negate i)-         return (Local t' o)-  setSecondFraction h (Local t o@Nothing)-    = do t' <- setSecondFraction h t-         return (Local t' o)-  setSecondFraction h (Local t o@(Just 0))-    = do t' <- setSecondFraction h t-         return (Local t' o)-  setSecondFraction h (Local t o@(Just i))-    = do t' <- addSecondFractions i t >>= setSecondFraction h >>= addSecondFractions (negate i)-         return (Local t' o)+  setHour h (Local o@Nothing t)+    = Local o <$> setHour h t+  setHour h (Local o@(Just 0) t)+    = Local o <$> setHour h t+  setHour h (Local o@(Just i) t)+    = Local o <$> ( addSecondFractions i t >>= setHour h >>= addSecondFractions (negate i) )+  setMinute h (Local o@Nothing t)+    = Local o <$> setMinute h t+  setMinute h (Local o@(Just 0) t)+    = Local o <$> setMinute h t+  setMinute h (Local o@(Just i) t)+    = Local o <$> ( addSecondFractions i t >>= setMinute h >>= addSecondFractions (negate i) )+  setSecond h (Local o@Nothing t)+    = Local o <$> setSecond h t+  setSecond h (Local o@(Just 0) t)+    = Local o <$> setSecond h t+  setSecond h (Local o@(Just i) t)+    = Local o <$> ( addSecondFractions i t >>= setSecond h >>= addSecondFractions (negate i) )+  setSecondFraction h (Local o@Nothing t)+    = Local o <$> setSecondFraction h t+  setSecondFraction h (Local o@(Just 0) t)+    = Local o <$> setSecondFraction h t+  setSecondFraction h (Local o@(Just i) t)+    = Local o <$> ( addSecondFractions i t >>= setSecondFraction h >>= addSecondFractions (negate i) )    -- This one is necessary to override, because the overflow should   -- ripple into the date part.
+ Data/UTC/Type/Exception.hs view
@@ -0,0 +1,18 @@+{-# LANGUAGE DeriveDataTypeable #-}+module Data.UTC.Type.Exception where++import Control.Exception++import Data.Typeable++-- | All non-total functions within this library throw a 'UtcException' exception+--   within a 'Control.Monad.Catch.MonadThrow' context. Use 'Control.Monad.Catch.MonadCatch'+--   to specifically catch this exception.+--+--   The 'Prelude.String' contains information that might be+--   useful for debugging, but its specific form is undefined and must not be relied on.+data UtcException+   = UtcException String+   deriving (Show, Typeable)++instance Exception UtcException
Data/UTC/Type/Local.hs view
@@ -1,13 +1,11 @@ {-# LANGUAGE Safe, FlexibleInstances #-} module Data.UTC.Type.Local   ( Local (..)-  , unknown   ) where  import Data.Maybe  import Data.UTC.Class.Epoch-import Data.UTC.Class.Midnight import Data.UTC.Class.IsTime import Data.UTC.Type.Time @@ -18,109 +16,87 @@ --   summer or winter time into account. data Local time    = Local -     { -- | The time to be interpreted as UTC+00:00 (__W__estern __E__uropean __T__ime)-       utc    :: time-     , -- | ['Nothing'] The local offset is unknown (behaves like __W__estern __E__uropean __T__ime)+     { -- | ['Nothing'] The local offset is unknown (behaves like __W__estern __E__uropean __T__ime)        --        -- ['Just' 0] UTC+00:00 (__W__estern __E__uropean __T__ime)        --        -- ['Just' 3600] UTC+01:00 (__C__entral __E__uropean __T__ime)        offset :: Maybe Rational+       -- | The time to be interpreted as UTC+00:00 (__W__estern __E__uropean __T__ime)+     , utc    :: time      }  instance Eq t => Eq (Local t) where-  (==) (Local a _) (Local b _)+  (==) (Local _ a) (Local _ b)     = a == b  instance Ord t => Ord (Local t) where-  compare (Local a _) (Local b _)+  compare (Local _ a) (Local _ b)     = compare a b  instance Epoch t => Epoch (Local t) where   epoch-    = unknown epoch--instance Midnight t => Midnight (Local t) where-  midnight-    = unknown midnight+    = Local Nothing epoch  instance Functor Local where-  fmap f (Local t o)-    = Local (f t) o+  fmap f (Local o t)+    = Local o (f t)  instance Bounded t => Bounded (Local t) where-  minBound  = unknown minBound-  maxBound  = unknown maxBound+  minBound  = Local Nothing minBound+  maxBound  = Local Nothing maxBound  -- assumption: addSecondFractions for Time is always successful instance IsTime (Local Time) where-  hour (Local t Nothing)+  hour (Local Nothing t)     = hour t-  hour (Local t (Just 0))+  hour (Local (Just 0) t)     = hour t-  hour (Local t (Just o))+  hour (Local (Just o) t)     = hour     $ fromMaybe undefined $ addSecondFractions o t-  minute (Local t Nothing)+  minute (Local Nothing t)     = minute t-  minute (Local t (Just 0))+  minute (Local (Just 0) t)     = minute t-  minute (Local t (Just o))+  minute (Local (Just o) t)     = minute     $ fromMaybe undefined $ addSecondFractions o t-  second (Local t Nothing)+  second (Local Nothing t)     = second t-  second (Local t (Just 0))+  second (Local (Just 0) t)     = second t-  second  (Local t (Just o))+  second  (Local (Just o) t)     = second     $ fromMaybe undefined $ addSecondFractions o t-  secondFraction (Local t Nothing)+  secondFraction (Local Nothing t)     = secondFraction t-  secondFraction (Local t (Just 0))+  secondFraction (Local (Just 0) t)     = secondFraction t-  secondFraction (Local t (Just o))+  secondFraction (Local (Just o) t)     = secondFraction     $ fromMaybe undefined $ addSecondFractions o t-  setHour h (Local t o@Nothing)-    = do t' <- setHour h t-         return (Local t' o)-  setHour h (Local t o@(Just 0))-    = do t' <- setHour h t-         return (Local t' o)-  setHour h (Local t o@(Just i))-    = do t' <- addSecondFractions i t >>= setHour h >>= addSecondFractions (negate i)-         return (Local t' o)-  setMinute h (Local t o@Nothing)-    = do t' <- setMinute h t-         return (Local t' o)-  setMinute h (Local t o@(Just 0))-    = do t' <- setMinute h t-         return (Local t' o)-  setMinute h (Local t o@(Just i))-    = do t' <- addSecondFractions i t >>= setMinute h >>= addSecondFractions (negate i)-         return (Local t' o)-  setSecond h (Local t o@Nothing)-    = do t' <- setSecond h t-         return (Local t' o)-  setSecond h (Local t o@(Just 0))-    = do t' <- setSecond h t-         return (Local t' o)-  setSecond h (Local t o@(Just i))-    = do t' <- addSecondFractions i t >>= setSecond h >>= addSecondFractions (negate i)-         return (Local t' o)-  setSecondFraction h (Local t o@Nothing)-    = do t' <- setSecondFraction h t-         return (Local t' o)-  setSecondFraction h (Local t o@(Just 0))-    = do t' <- setSecondFraction h t-         return (Local t' o)-  setSecondFraction h (Local t o@(Just i))-    = do t' <- addSecondFractions i t >>= setSecondFraction h >>= addSecondFractions (negate i)-         return (Local t' o)----unknown :: t -> Local t-unknown t-  = Local t Nothing+  setHour h (Local o@Nothing t)+    = Local o <$> setHour h t+  setHour h (Local o@(Just 0) t)+    = Local o <$> setHour h t+  setHour h (Local o@(Just i) t)+    = Local o <$> ( addSecondFractions i t >>= setHour h >>= addSecondFractions (negate i) )+  setMinute h (Local o@Nothing t)+    = Local o <$> setMinute h t+  setMinute h (Local o@(Just 0) t)+    = Local o <$> setMinute h t+  setMinute h (Local o@(Just i) t)+    = Local o <$> ( addSecondFractions i t >>= setMinute h >>= addSecondFractions (negate i) )+  setSecond h (Local o@Nothing t)+    = Local o <$> setSecond h t+  setSecond h (Local o@(Just 0) t)+    = Local o <$> setSecond h t+  setSecond h (Local o@(Just i) t)+    = Local o <$> ( addSecondFractions i t >>= setSecond h >>= addSecondFractions (negate i) )+  setSecondFraction h (Local o@Nothing t)+    = Local o <$> setSecondFraction h t+  setSecondFraction h (Local o@(Just 0) t)+    = Local o <$> setSecondFraction h t+  setSecondFraction h (Local o@(Just i) t)+    = Local o <$> ( addSecondFractions i t >>= setSecondFraction h >>= addSecondFractions (negate i) )
Data/UTC/Type/Time.hs view
@@ -1,33 +1,49 @@ module Data.UTC.Type.Time   ( Time ()-  , midnight   ) where +import Control.Monad.Catch+ import Data.Ratio -import Data.UTC.Class.Midnight+import Data.UTC.Class.Epoch import Data.UTC.Class.IsTime import Data.UTC.Class.IsUnixTime import Data.UTC.Internal+import Data.UTC.Type.Exception  -- | This type represents time instants during a day (__00:00:00 - 23:59:59.999__..) --   with arbitrary precision (uses 'Prelude.Integer' internally). -- --   * The internal structure is not exposed to avoid the creation of --     invalid values.---     Use 'Data.UTC.midnight' or a parser to construct values.+--     Use 'Data.UTC.epoch' or a parser to construct values. --   * The instance of 'Prelude.Show' is only meant for debugging purposes --     and is subject to change.+--+-- > > show (epoch :: Time)+-- > 00:00:00 data Time    = Time      { tHour           :: Integer      , tMinute         :: Integer      , tSecond         :: Integer      , tSecondFraction :: Rational-     } deriving (Eq, Ord, Show)+     } deriving (Eq, Ord) -instance Midnight Time where-  midnight+instance Show Time where+  show (Time hh mm ss ff)+    = concat+        [ fixedDecimal 2 hh+        , ":"+        , fixedDecimal 2 mm+        , ":"+        , fixedDecimal 2 ss+        , decimalFraction 12 ff+        ]++instance Epoch Time where+  epoch     = Time 0 0 0 0  instance IsUnixTime Time where@@ -55,14 +71,14 @@     = tSecondFraction    setHour x t-    | x < 0 || 23 < x = fail   $ "Time.setHour "           ++ show x+    | x < 0 || 23 < x = throwM $ UtcException $ "Time: setHour "           ++ show x ++ " " ++ show t     | otherwise       = return $ t { tHour           = x }   setMinute x t-    | x < 0 || 59 < x = fail   $ "Time.setMinute "         ++ show x+    | x < 0 || 59 < x = throwM $ UtcException $ "Time: setMinute "         ++ show x ++ " " ++ show t     | otherwise       = return $ t { tMinute         = x }   setSecond x t-    | x < 0 || 59 < x = fail   $ "Time.setSecond "         ++ show x+    | x < 0 || 59 < x = throwM $ UtcException $ "Time: setSecond "         ++ show x ++ " " ++ show t     | otherwise       = return $ t { tSecond         = x }   setSecondFraction x t-    | x < 0 || 1 <= x = fail   $ "Time.setSecondFraction " ++ show x+    | x < 0 || 1 <= x = throwM $ UtcException $ "Time: setSecondFraction " ++ show x ++ " " ++ show t     | otherwise       = return $ t { tSecondFraction = x }
tests/Test.hs view
@@ -5,8 +5,6 @@ import Test.Framework (Test) import Test.Framework.Providers.QuickCheck2 (testProperty) -import Data.String- import Data.UTC  import Data.UTC.Internal.Test (test)@@ -22,7 +20,7 @@      , testGroup "instance Time DateTime"      $ testTimeInstance (epoch     :: DateTime)      , testGroup "instance Time Time"-     $ testTimeInstance (midnight  :: Time)+     $ testTimeInstance (epoch  :: Time)       , Data.UTC.Internal.Test.test      , Data.UTC.Class.IsDate.Test.test@@ -125,12 +123,12 @@          , ("10", setSecondFraction 1.1 t)          ] -testUnixTimeInstance :: (Show t, IsUnixTime t, IsString t,Eq t) => t -> [Test]+testUnixTimeInstance :: (Show t, IsUnixTime t, Eq t, IsTime t, IsDate t) => t -> [Test] testUnixTimeInstance t   = (map        (\(i64,s)->         testProperty ("fromUnixSeconds " ++ show i64 ++ ") == Just " ++ show s)-        $  (fromUnixSeconds i64) === Just (fromString s `asTypeOf` t)+        $  (fromUnixSeconds i64) === (utc `fmap` parseRfc3339 s) `asTypeOf` Just t        )        unixEpochMsRfc3339TimeTuples       )@@ -138,7 +136,7 @@       (map        (\(i64,s)->         testProperty ("unixSeconds (" ++ show s ++ ") == " ++ show i64)-        $ unixSeconds (fromString s `asTypeOf` t) === i64+        $ unixSeconds `fmap` ((utc `fmap` parseRfc3339 s) `asTypeOf` Just t) === Just i64        )        unixEpochMsRfc3339TimeTuples       )
utc.cabal view
@@ -1,5 +1,5 @@ name:                utc-version:             0.1.0.1+version:             0.2.0.0 stability:           experimental synopsis:            A pragmatic time and date library. description:         This library aims to supply you with common@@ -15,12 +15,6 @@                          specific or maybe more efficient time and date types. Implement the                          interfaces and get all the parsing and rendering functions for free!                      .-                     This is a work in progress!-                     .-                     Try it out and play with it. Tell me what you think-                     about the API design and naming, but __DON'T USE IT-                     IN PRODUCTION YET!__-                     .                      Bug reports or (even better) tests are welcome. license:             MIT license-file:        LICENSE@@ -39,13 +33,13 @@                    , bytestring >= 0.10.4.0                    , attoparsec                    , clock >= 0.3 && < 0.5+                   , exceptions >= 0.4   ghc-options:       -Wall   hs-source-dirs:    .   default-language:  Haskell98   exposed-modules:   Data.UTC-                   , Data.UTC.Class+  other-modules:     Data.UTC.Class                    , Data.UTC.Class.Epoch-                   , Data.UTC.Class.Midnight                    , Data.UTC.Class.IsDate                    , Data.UTC.Class.IsTime                    , Data.UTC.Class.IsUnixTime@@ -55,9 +49,11 @@                    , Data.UTC.Type.Time                    , Data.UTC.Type.DateTime                    , Data.UTC.Type.Local+                   , Data.UTC.Type.Exception                    , Data.UTC.Format.Rfc3339+                   , Data.UTC.Format.Iso8601                    , Data.UTC.Internal-  other-modules:     Data.UTC.Format.Rfc3339.Parser+                   , Data.UTC.Format.Rfc3339.Parser                    , Data.UTC.Format.Rfc3339.Builder  Test-Suite test@@ -66,9 +62,9 @@   ghc-options:       -Wall -O2   hs-source-dirs:    tests .   other-modules:     Data.UTC+                   -- in library unexposed modules                    , Data.UTC.Class                    , Data.UTC.Class.Epoch-                   , Data.UTC.Class.Midnight                    , Data.UTC.Class.IsDate                    , Data.UTC.Class.IsDate.Test                    , Data.UTC.Class.IsTime@@ -79,8 +75,9 @@                    , Data.UTC.Type.Time                    , Data.UTC.Type.DateTime                    , Data.UTC.Type.Local+                   , Data.UTC.Type.Exception                    , Data.UTC.Format.Rfc3339-                   -- in library unexposed modules+                   , Data.UTC.Format.Iso8601                    , Data.UTC.Format.Rfc3339.Parser                    , Data.UTC.Format.Rfc3339.Builder                    , Data.UTC.Internal@@ -90,6 +87,7 @@                    , bytestring >= 0.10.4.0                    , attoparsec                    , clock >= 0.3 && < 0.5+                   , exceptions >= 0.4                    -- additional deps for testing                    , Cabal                    , test-framework >= 0.8.0.2