1 {-# LANGUAGE FlexibleContexts #-}
2 module Data.Time.HTTP.Common
25 , assertGregorianDateIsGood
26 , assertTimeOfDayIsGood
32 import Data.Time.Calendar.WeekDate
34 shortWeekDayName :: Int -> String
35 shortWeekDayName 1 = "Mon"
36 shortWeekDayName 2 = "Tue"
37 shortWeekDayName 3 = "Wed"
38 shortWeekDayName 4 = "Thu"
39 shortWeekDayName 5 = "Fri"
40 shortWeekDayName 6 = "Sat"
41 shortWeekDayName 7 = "Sun"
42 shortWeekDayName n = error ("shortWeekDayName: unknown day number: " ++ show n)
44 shortWeekDayNameP :: Stream s m Char => ParsecT s u m Int
46 = choice [ string "Mon" >> return 1
48 >> choice [ string "ue" >> return 2
49 , string "hu" >> return 4
51 , string "Wed" >> return 3
52 , string "Fri" >> return 5
54 >> choice [ string "at" >> return 6
55 , string "un" >> return 7
59 longWeekDayName :: Int -> String
60 longWeekDayName 1 = "Monday"
61 longWeekDayName 2 = "Tuesday"
62 longWeekDayName 3 = "Wednesday"
63 longWeekDayName 4 = "Thursday"
64 longWeekDayName 5 = "Friday"
65 longWeekDayName 6 = "Saturday"
66 longWeekDayName 7 = "Sunday"
68 longWeekDayNameP :: Stream s m Char => ParsecT s u m Int
70 = choice [ string "Monday" >> return 1
72 >> choice [ string "uesday" >> return 2
73 , string "hursday" >> return 4
75 , string "Wednesday" >> return 3
76 , string "Friday" >> return 5
78 >> choice [ string "aturday" >> return 6
79 , string "unday" >> return 7
83 shortMonthName :: Int -> String
84 shortMonthName 1 = "Jan"
85 shortMonthName 2 = "Feb"
86 shortMonthName 3 = "Mar"
87 shortMonthName 4 = "Apr"
88 shortMonthName 5 = "May"
89 shortMonthName 6 = "Jun"
90 shortMonthName 7 = "Jul"
91 shortMonthName 8 = "Aug"
92 shortMonthName 9 = "Sep"
93 shortMonthName 10 = "Oct"
94 shortMonthName 11 = "Nov"
95 shortMonthName 12 = "Dec"
96 shortMonthName n = error ("shortMonthName: unknown month number: " ++ show n)
98 shortMonthNameP :: Stream s m Char => ParsecT s u m Int
101 >> choice [ string "an" >> return 1
103 >> choice [ char 'n' >> return 6
104 , char 'l' >> return 7
107 , string "Feb" >> return 2
109 >> choice [ char 'r' >> return 3
110 , char 'y' >> return 5
113 >> choice [ string "pr" >> return 4
114 , string "ug" >> return 8
116 , string "Sep" >> return 9
117 , string "Oct" >> return 10
118 , string "Nov" >> return 11
119 , string "Dec" >> return 12
122 longMonthName :: Int -> String
123 longMonthName 1 = "January"
124 longMonthName 2 = "February"
125 longMonthName 3 = "March"
126 longMonthName 4 = "April"
127 longMonthName 5 = "May"
128 longMonthName 6 = "June"
129 longMonthName 7 = "July"
130 longMonthName 8 = "August"
131 longMonthName 9 = "September"
132 longMonthName 10 = "October"
133 longMonthName 11 = "November"
134 longMonthName 12 = "December"
135 longMonthName n = error ("longMonthName: unknown month number: " ++ show n)
137 longMonthNameP :: Stream s m Char => ParsecT s u m Int
140 >> choice [ string "anuary" >> return 1
142 >> choice [ string "ne" >> return 6
143 , string "ly" >> return 7
146 , string "February" >> return 2
148 >> choice [ string "rch" >> return 3
149 , char 'y' >> return 5
152 >> choice [ string "pril" >> return 4
153 , string "ugust" >> return 8
155 , string "September" >> return 9
156 , string "October" >> return 10
157 , string "November" >> return 11
158 , string "December" >> return 12
161 show4 :: Integral i => i -> String
163 | i >= 0 && i < 10 = "000" ++ show i
164 | i >= 0 && i < 100 = "00" ++ show i
165 | i >= 0 && i < 1000 = '0' : show i
166 | i >= 0 && i < 10000 = show i
167 | otherwise = error ("show4: the integer i must satisfy 0 <= i < 10000: " ++ show i)
169 show2 :: Integral i => i -> String
171 | i >= 0 && i < 10 = '0' : show i
172 | i >= 0 && i < 100 = show i
173 | otherwise = error ("show2: the integer i must satisfy 0 <= i < 100: " ++ show i)
175 read4 :: (Stream s m Char, Num n) => ParsecT s u m n
176 read4 = do n1 <- digit'
180 return (n1 * 1000 + n2 * 100 + n3 * 10 + n4)
182 read2 :: (Stream s m Char, Num n) => ParsecT s u m n
183 read2 = do n1 <- digit'
185 return (n1 * 10 + n2)
187 digit' :: (Stream s m Char, Num n) => ParsecT s u m n
188 digit' = liftM fromC digit
190 fromC :: Num n => Char -> n
203 show4digitsTZ :: TimeZone -> String
205 = case timeZoneMinutes tz of
206 offset | offset < 0 -> '-' : showTZ' (negate offset)
207 | otherwise -> '+' : showTZ' offset
210 = let h = offset `div` 60
215 read4digitsTZ :: Stream s m Char => ParsecT s u m TimeZone
217 = do sign <- (char '+' >> return 1)
219 (char '-' >> return (-1))
223 timeZoneMinutes = sign * (hour * 60 + minute)
224 , timeZoneSummerOnly = False
225 , timeZoneName = timeZoneOffsetString tz
229 assertWeekDayIsGood :: Stream s m t => Int -> Day -> ParsecT s u m ()
230 assertWeekDayIsGood givenWD gregDay
231 = let (_, _, correctWD ) = toWeekDate gregDay
232 (year, month, day) = toGregorian gregDay
234 unless (givenWD == correctWD)
236 $ concat [ "Gregorian day "
243 , longWeekDayName correctWD
245 , longWeekDayName givenWD
248 assertGregorianDateIsGood :: Stream s m t => Integer -> Int -> Int -> ParsecT s u m Day
249 assertGregorianDateIsGood year month day
250 = case fromGregorianValid year month day of
252 -> fail $ concat [ "Invalid gregorian day: "
262 assertTimeOfDayIsGood :: Stream s m t => Int -> Int -> Pico -> ParsecT s u m TimeOfDay
263 assertTimeOfDayIsGood hour minute second
264 = case makeTimeOfDayValid hour minute second of
266 -> fail $ concat [ "Invalid time of day: "
271 , showFixed True second