+
+import qualified Text.Parsec as P
+
+import Data.Time
+import Data.Time.Calendar.WeekDate
+import Data.Time.HTTP.Common
+import Data.Time.RFC822.Parsec
+
+-- |Format a 'ZonedTime' in RFC 822.
+format :: ZonedTime -> String
+format zonedTime
+ = let localTime = zonedTimeToLocalTime zonedTime
+ timeZone = zonedTimeZone zonedTime
+ (year, month, day) = toGregorian (localDay localTime)
+ (_, _, week) = toWeekDate (localDay localTime)
+ timeOfDay = localTimeOfDay localTime
+ in
+ concat [ shortWeekDayName week
+ , ", "
+ , show2 day
+ , " "
+ , shortMonthName month
+ , " "
+ , show2 (year `mod` 100)
+ , " "
+ , show2 (todHour timeOfDay)
+ , ":"
+ , show2 (todMin timeOfDay)
+ , ":"
+ , show2 (floor (todSec timeOfDay))
+ , " "
+ , showRFC822TimeZone timeZone
+ ]
+
+showRFC822TimeZone :: TimeZone -> String
+showRFC822TimeZone tz
+ | timeZoneMinutes tz == 0 = "GMT"
+ | otherwise = show4digitsTZ tz
+
+-- |Parse an RFC 822 date and time string. When the string can't be
+-- parsed, it returns 'Nothing'.
+parse :: String -> Maybe ZonedTime
+parse src = case P.parse p "" src of
+ Right zt -> Just zt
+ Left _ -> Nothing
+ where
+ p = do zt <- rfc822DateAndTime
+ _ <- P.eof
+ return zt