--- /dev/null
+module Data.Time.W3C.Format
+ ( format
+ )
+ where
+
+import Data.Convertible
+import Data.Fixed
+import Data.Time
+import Data.Time.W3C.Types
+
+
+format :: Convertible t W3CDateTime => t -> String
+format = format' . convert
+ where
+ format' (W3CDateTime year Nothing Nothing Nothing Nothing Nothing Nothing)
+ = show4 year
+
+ format' (W3CDateTime year (Just month) Nothing Nothing Nothing Nothing Nothing)
+ = concat [show4 year, "-", show2 month]
+
+ format' (W3CDateTime year (Just month) (Just day) Nothing Nothing Nothing Nothing)
+ = concat [show4 year, "-", show2 month, "-", show2 day]
+
+ format' (W3CDateTime year (Just month) (Just day) (Just hour) (Just minute) Nothing (Just tz))
+ = concat [ show4 year
+ , "-"
+ , show2 month
+ , "-"
+ , show2 day
+ , "T"
+ , show2 hour
+ , ":"
+ , show2 minute
+ , showTZ tz
+ ]
+
+ format' (W3CDateTime year (Just month) (Just day) (Just hour) (Just minute) (Just second) (Just tz))
+ = concat [ show4 year
+ , "-"
+ , show2 month
+ , "-"
+ , show2 day
+ , "T"
+ , show2 hour
+ , ":"
+ , show2 minute
+ , ":"
+ , case properFraction second :: (Int, Pico) of
+ (int, 0 ) -> show2 int
+ (int, frac) -> show2 int ++ tail (show frac)
+ , showTZ tz
+ ]
+
+ format' w = error ("Invalid W3C Date and Time: " ++ show w)
+
+show4 :: Integral i => i -> String
+show4 i
+ | i >= 0 && i < 10 = "000" ++ show i
+ | i >= 0 && i < 100 = "00" ++ show i
+ | i >= 0 && i < 1000 = "0" ++ show i
+ | i >= 0 && i < 10000 = show i
+ | otherwise = error ("show4: the integer i must satisfy 0 <= i < 10000: " ++ show i)
+
+show2 :: Integral i => i -> String
+show2 i
+ | i >= 0 && i < 10 = "0" ++ show i
+ | i >= 0 && i < 100 = show i
+ | otherwise = error ("show2: the integer i must satisfy 0 <= i < 100: " ++ show i)
+
+showTZ :: TimeZone -> String
+showTZ tz
+ = case timeZoneMinutes tz of
+ offset | offset < 0 -> '-' : showTZ' (negate offset)
+ | offset == 0 -> "Z"
+ | otherwise -> '+' : showTZ' offset
+ where
+ showTZ' offset
+ = let h = offset `div` 60
+ m = offset - h * 60
+ in
+ concat [show2 h, ":", show2 m]