1 -- |This module provides functions to parse and format HTTP\/1.1 date
4 -- The HTTP\/1.1 specification (RFC 2616) says that HTTP\/1.1 clients
5 -- and servers which parse the date value MUST accept all the
6 -- following formats, though they MUST only generate the RFC 1123
7 -- format for representing HTTP-date values in header fields:
9 -- > Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
10 -- > Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
11 -- > Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
13 -- It also says that all HTTP date\/time stamps MUST be represented in
14 -- Greenwich Mean Time (GMT), without exception. For the purposes of
15 -- HTTP, GMT is exactly equal to UTC (Coordinated Universal
16 -- Time). This is indicated in the first two formats by the inclusion
17 -- of @\"GMT\"@ as the three-letter abbreviation for time zone, and
18 -- MUST be assumed when reading the asctime format.
20 -- > HTTP-date = rfc1123-date | rfc850-date | asctime-date
21 -- > rfc1123-date = wkday "," SP date1 SP time SP "GMT"
22 -- > rfc850-date = weekday "," SP date2 SP time SP "GMT"
23 -- > asctime-date = wkday SP date3 SP time SP 4DIGIT
24 -- > date1 = 2DIGIT SP month SP 4DIGIT
25 -- > ; day month year (e.g., 02 Jun 1982)
26 -- > date2 = 2DIGIT "-" month "-" 2DIGIT
27 -- > ; day-month-year (e.g., 02-Jun-82)
28 -- > date3 = month SP ( 2DIGIT | ( SP 1DIGIT ))
29 -- > ; month day (e.g., Jun 2)
30 -- > time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
31 -- > ; 00:00:00 - 23:59:59
32 -- > wkday = "Mon" | "Tue" | "Wed"
33 -- > | "Thu" | "Fri" | "Sat" | "Sun"
34 -- > weekday = "Monday" | "Tuesday" | "Wednesday"
35 -- > | "Thursday" | "Friday" | "Saturday" | "Sunday"
36 -- > month = "Jan" | "Feb" | "Mar" | "Apr"
37 -- > | "May" | "Jun" | "Jul" | "Aug"
38 -- > | "Sep" | "Oct" | "Nov" | "Dec"
45 import qualified Data.Time.RFC1123 as RFC1123
46 import qualified Text.Parsec as P
49 import Data.Time.HTTP.Parsec
51 -- |Format an 'UTCTime' in RFC 1123 date and time.
52 format :: UTCTime -> String
54 = let timeZone = TimeZone 0 False "GMT"
55 zonedTime = utcToZonedTime timeZone utcTime
57 RFC1123.format zonedTime
59 -- |Parse a date and time string in any of RFC 822, RFC 1123, RFC 850
60 -- and ANSI C's asctime() formats. When the string can't be parsed, it
63 -- This function is even more permissive than what HTTP\/1.1
64 -- specifies. That is, it accepts 2-digit years in RFC 822, omitted
65 -- separator symbols in RFC 850, omitted sec fields, and non-GMT time
66 -- zones. I believe this behavior will not cause a problem but you
68 parse :: String -> Maybe UTCTime
69 parse src = case P.parse p "" src of
73 p = do zt <- rfc2616DateAndTime