diff --git a/Data/UTC.hs b/Data/UTC.hs
--- a/Data/UTC.hs
+++ b/Data/UTC.hs
@@ -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
 --
diff --git a/Data/UTC/Class.hs b/Data/UTC/Class.hs
--- a/Data/UTC/Class.hs
+++ b/Data/UTC/Class.hs
@@ -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
diff --git a/Data/UTC/Class/HasUnixTime.hs b/Data/UTC/Class/HasUnixTime.hs
--- a/Data/UTC/Class/HasUnixTime.hs
+++ b/Data/UTC/Class/HasUnixTime.hs
@@ -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"
 
diff --git a/Data/UTC/Class/IsDate.hs b/Data/UTC/Class/IsDate.hs
--- a/Data/UTC/Class/IsDate.hs
+++ b/Data/UTC/Class/IsDate.hs
@@ -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
diff --git a/Data/UTC/Class/IsTime.hs b/Data/UTC/Class/IsTime.hs
--- a/Data/UTC/Class/IsTime.hs
+++ b/Data/UTC/Class/IsTime.hs
@@ -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
diff --git a/Data/UTC/Class/IsUnixTime.hs b/Data/UTC/Class/IsUnixTime.hs
--- a/Data/UTC/Class/IsUnixTime.hs
+++ b/Data/UTC/Class/IsUnixTime.hs
@@ -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
diff --git a/Data/UTC/Class/Midnight.hs b/Data/UTC/Class/Midnight.hs
deleted file mode 100644
--- a/Data/UTC/Class/Midnight.hs
+++ /dev/null
@@ -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
-
diff --git a/Data/UTC/Format/Iso8601.hs b/Data/UTC/Format/Iso8601.hs
new file mode 100644
--- /dev/null
+++ b/Data/UTC/Format/Iso8601.hs
@@ -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
+
diff --git a/Data/UTC/Format/Rfc3339.hs b/Data/UTC/Format/Rfc3339.hs
--- a/Data/UTC/Format/Rfc3339.hs
+++ b/Data/UTC/Format/Rfc3339.hs
@@ -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
diff --git a/Data/UTC/Format/Rfc3339/Builder.hs b/Data/UTC/Format/Rfc3339/Builder.hs
--- a/Data/UTC/Format/Rfc3339/Builder.hs
+++ b/Data/UTC/Format/Rfc3339/Builder.hs
@@ -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
diff --git a/Data/UTC/Format/Rfc3339/Parser.hs b/Data/UTC/Format/Rfc3339/Parser.hs
--- a/Data/UTC/Format/Rfc3339/Parser.hs
+++ b/Data/UTC/Format/Rfc3339/Parser.hs
@@ -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
diff --git a/Data/UTC/Internal.hs b/Data/UTC/Internal.hs
--- a/Data/UTC/Internal.hs
+++ b/Data/UTC/Internal.hs
@@ -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)
diff --git a/Data/UTC/Type.hs b/Data/UTC/Type.hs
--- a/Data/UTC/Type.hs
+++ b/Data/UTC/Type.hs
@@ -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
diff --git a/Data/UTC/Type/Date.hs b/Data/UTC/Type/Date.hs
--- a/Data/UTC/Type/Date.hs
+++ b/Data/UTC/Type/Date.hs
@@ -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
 
diff --git a/Data/UTC/Type/DateTime.hs b/Data/UTC/Type/DateTime.hs
--- a/Data/UTC/Type/DateTime.hs
+++ b/Data/UTC/Type/DateTime.hs
@@ -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.
diff --git a/Data/UTC/Type/Exception.hs b/Data/UTC/Type/Exception.hs
new file mode 100644
--- /dev/null
+++ b/Data/UTC/Type/Exception.hs
@@ -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
diff --git a/Data/UTC/Type/Local.hs b/Data/UTC/Type/Local.hs
--- a/Data/UTC/Type/Local.hs
+++ b/Data/UTC/Type/Local.hs
@@ -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) )
diff --git a/Data/UTC/Type/Time.hs b/Data/UTC/Type/Time.hs
--- a/Data/UTC/Type/Time.hs
+++ b/Data/UTC/Type/Time.hs
@@ -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 }
diff --git a/tests/Test.hs b/tests/Test.hs
--- a/tests/Test.hs
+++ b/tests/Test.hs
@@ -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
       )
diff --git a/utc.cabal b/utc.cabal
--- a/utc.cabal
+++ b/utc.cabal
@@ -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
