1 module Rakka.W3CDateTime
9 import Prelude hiding (min)
10 import Text.ParserCombinators.Parsec
14 formatW3CDateTime :: ZonedTime -> String
15 formatW3CDateTime zonedTime
16 = formatLocalTime (zonedTimeToLocalTime zonedTime)
18 formatTimeZone (zonedTimeZone zonedTime)
20 formatLocalTime :: LocalTime -> String
21 formatLocalTime localTime
22 = let (year, month, day) = toGregorian (localDay localTime)
23 timeOfDay = localTimeOfDay localTime
24 (secInt, secFrac) = properFraction (todSec timeOfDay)
26 (printf "%04d-%02d-%02dT%02d:%02d:%02d"
36 else tail (show secFrac))
38 formatTimeZone :: TimeZone -> String
40 = case timeZoneMinutes tz of
41 offset | offset < 0 -> '-':(showTZ $ negate offset)
43 | otherwise -> '+':(showTZ offset)
45 showTZ :: Int -> String
47 = let hour = offset `div` 60
48 minute = offset - hour * 60
50 show2 hour ++ ":" ++ show2 minute
52 show2 :: Int -> String
53 show2 n | n < 10 = '0':(show n)
57 parseW3CDateTime :: String -> Maybe ZonedTime
59 = case parse w3cDateTime "" src of
63 w3cDateTime :: Parser ZonedTime
64 w3cDateTime = do year <- liftM read (count 4 digit)
65 mon <- option 1 (char '-' >> liftM read (count 2 digit))
66 day <- option 1 (char '-' >> liftM read (count 2 digit))
67 (hour, min, sec, offMin)
68 <- option (0, 0, 0, 0) time
71 let julianDay = fromGregorian year mon day
72 timeOfDay = TimeOfDay hour min (fromRational $ toRational sec)
73 localTime = LocalTime julianDay timeOfDay
74 timeZone = minutesToTimeZone offMin
75 zonedTime = ZonedTime localTime timeZone
79 time :: Parser (Int, Int, Double, Int)
81 hour <- liftM read (count 2 digit)
83 min <- liftM read (count 2 digit)
84 sec <- option 0 $ do char ':'
85 secInt <- count 2 digit
86 secFrac <- option "" $ do c <- char '.'
89 return $ read (secInt ++ secFrac)
90 offMin <- (char 'Z' >> return 0)
92 (do sign <- (char '+' >> return 1)
94 (char '-' >> return (-1))
95 h <- liftM read (count 2 digit)
97 m <- liftM read (count 2 digit)
98 return $ sign * h * 60 + m)
99 return (hour, min, sec, offMin)