X-Git-Url: http://git.cielonegro.org/gitweb.cgi?p=Lucu.git;a=blobdiff_plain;f=Network%2FHTTP%2FLucu%2FRFC1123DateTime.hs;h=f86b2b1111dd206e965eff7f59edd87569c52cc4;hp=4606bafddce634cb3c7fdf009ba8c27a91c22ae0;hb=3d017dd65ddede9a11c5b7a34a91e04340e67bc4;hpb=e1e74c8f81ccbc57bf5a09987b0a9dd42648f020 diff --git a/Network/HTTP/Lucu/RFC1123DateTime.hs b/Network/HTTP/Lucu/RFC1123DateTime.hs index 4606baf..f86b2b1 100644 --- a/Network/HTTP/Lucu/RFC1123DateTime.hs +++ b/Network/HTTP/Lucu/RFC1123DateTime.hs @@ -9,46 +9,56 @@ module Network.HTTP.Lucu.RFC1123DateTime where import Control.Monad -import Data.ByteString.Base (LazyByteString) +import Data.Time +import Data.Time.Calendar.WeekDate +import qualified Data.ByteString.Lazy as Lazy (ByteString) import Network.HTTP.Lucu.Format import Network.HTTP.Lucu.Parser -import System.Time +import Prelude hiding (min) -month :: [String] -month = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] -week :: [String] -week = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"] +monthStr :: [String] +monthStr = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] + +weekStr :: [String] +weekStr = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"] -- |Format a 'System.Time.CalendarTime' to RFC 1123 Date and Time -- string. -formatRFC1123DateTime :: CalendarTime -> String -formatRFC1123DateTime time - = time `seq` - - id (week !! fromEnum (ctWDay time)) - ++ ", " ++ - fmtDec 2 (ctDay time) - ++ " " ++ - id (month !! fromEnum (ctMonth time)) - ++ " " ++ - fmtDec 4 (ctYear time) - ++ " " ++ - fmtDec 2 (ctHour time) - ++ ":" ++ - fmtDec 2 (ctMin time) - ++ ":" ++ - fmtDec 2 (ctSec time) - ++ " " ++ - id (ctTZName time) +formatRFC1123DateTime :: ZonedTime -> String +formatRFC1123DateTime zonedTime + = let localTime = zonedTimeToLocalTime zonedTime + timeZone = zonedTimeZone zonedTime + (year, month, day) = toGregorian (localDay localTime) + (_, _, week) = toWeekDate (localDay localTime) + timeOfDay = localTimeOfDay localTime + in + id (weekStr !! (week - 1)) + ++ ", " ++ + fmtDec 2 day + ++ " " ++ + id (monthStr !! (month - 1)) + ++ " " ++ + fmtDec 4 (fromInteger year) + ++ " " ++ + fmtDec 2 (todHour timeOfDay) + ++ ":" ++ + fmtDec 2 (todMin timeOfDay) + ++ ":" ++ + fmtDec 2 (floor (todSec timeOfDay)) + ++ " " ++ + id (timeZoneName timeZone) -- |Format a 'System.Time.ClockTime' to HTTP Date and Time. Time zone -- will be always UTC but prints as GMT. -formatHTTPDateTime :: ClockTime -> String -formatHTTPDateTime time - = time `seq` - formatRFC1123DateTime $! (\cal -> cal { ctTZName = "GMT" }) $! toUTCTime time +formatHTTPDateTime :: UTCTime -> String +formatHTTPDateTime utcTime + = let timeZone = TimeZone 0 False "GMT" + zonedTime = utcToZonedTime timeZone utcTime + in + formatRFC1123DateTime zonedTime + -- |Parse an HTTP Date and Time. -- @@ -64,20 +74,20 @@ formatHTTPDateTime time -- ...but currently this function only supports the RFC 1123 -- format. This is a violation of RFC 2616 so this should be fixed -- later. What a bother! -parseHTTPDateTime :: LazyByteString -> Maybe ClockTime +parseHTTPDateTime :: Lazy.ByteString -> Maybe UTCTime parseHTTPDateTime src = case parse httpDateTime src of (# Success ct, _ #) -> Just ct (# _ , _ #) -> Nothing -httpDateTime :: Parser ClockTime -httpDateTime = do foldl (<|>) failP (map string week) +httpDateTime :: Parser UTCTime +httpDateTime = do foldl (<|>) failP (map string weekStr) char ',' char ' ' day <- liftM read (count 2 digit) char ' ' - mon <- foldl (<|>) failP (map tryEqToFst (zip month [1..])) + mon <- foldl (<|>) failP (map tryEqToFst (zip monthStr [1..])) char ' ' year <- liftM read (count 4 digit) char ' ' @@ -85,24 +95,14 @@ httpDateTime = do foldl (<|>) failP (map string week) char ':' min <- liftM read (count 2 digit) char ':' - sec <- liftM read (count 2 digit) + sec <- liftM read (count 2 digit) :: Parser Int char ' ' string "GMT" eof - return $ toClockTime $ CalendarTime { - ctYear = year - , ctMonth = toEnum (mon - 1) - , ctDay = day - , ctHour = hour - , ctMin = min - , ctSec = sec - , ctPicosec = 0 - , ctTZ = 0 - , ctWDay = undefined - , ctYDay = undefined - , ctTZName = undefined - , ctIsDST = undefined - } + let julianDay = fromGregorian year mon day + timeOfDay = TimeOfDay hour min (fromIntegral sec) + utcTime = UTCTime julianDay (timeOfDayToTime timeOfDay) + return utcTime where tryEqToFst :: (String, a) -> Parser a tryEqToFst (str, a) = string str >> return a