]> gitweb @ CieloNegro.org - time-http.git/blob - Data/Time/Format/C.hs
Use data-default to provide fafault parsers; remove proxies.
[time-http.git] / Data / Time / Format / C.hs
1 {-# LANGUAGE
2     FlexibleInstances
3   , MultiParamTypeClasses
4   , OverloadedStrings
5   , TemplateHaskell
6   , TypeSynonymInstances
7   , UnicodeSyntax
8   #-}
9 -- |This module provides functions for ANSI C's date and time strings.
10 --
11 -- ANSI C's @ctime(3)@/@asctime(3)@ format looks like:
12 --
13 -- @Wdy Mon [D]D HH:MM:SS YYYY@
14 --
15 -- The exact syntax is as follows:
16 --
17 -- > date-time ::= wday SP month SP day SP time SP year
18 -- > wday      ::= "Mon" | "Tue" | "Wed" | "Thu"
19 -- >             | "Fri" | "Sat" | "Sun"
20 -- > month     ::= "Jan" | "Feb" | "Mar" | "Apr"
21 -- >             | "May" | "Jun" | "Jul" | "Aug"
22 -- >             | "Sep" | "Oct" | "Nov" | "Dec"
23 -- > day       ::= 2DIGIT | SP 1DIGIT
24 -- > time      ::= 2DIGIT ':' 2DIGIT [':' 2DIGIT]
25 -- > year      ::= 4DIGIT
26 module Data.Time.Format.C
27     ( C
28     )
29     where
30 import Data.Ascii (Ascii, AsciiBuilder)
31 import qualified Data.Ascii as A
32 import Data.Attoparsec.Char8
33 import Data.Convertible.Base
34 import Data.Default
35 import Data.Monoid.Unicode
36 import Data.Tagged
37 import Data.Time
38 import Data.Time.Calendar.WeekDate
39 import Data.Time.Format.HTTP.Common
40 import Prelude.Unicode
41
42 -- |The phantom type for conversions between ANSI C's date and time
43 -- strings and 'LocalTime'.
44 --
45 -- >>> convertSuccess (Tagged (LocalTime (ModifiedJulianDay 49662) (TimeOfDay 8 49 37)) :: Tagged C LocalTime)
46 -- "Sun Nov  6 08:49:37 1994"
47 data C
48
49 instance ConvertSuccess (Tagged C LocalTime) Ascii where
50     {-# INLINE convertSuccess #-}
51     convertSuccess = A.fromAsciiBuilder ∘ cs
52
53 instance ConvertSuccess (Tagged C LocalTime) AsciiBuilder where
54     {-# INLINE convertSuccess #-}
55     convertSuccess = toAsciiBuilder ∘ untag
56
57 instance ConvertAttempt Ascii (Tagged C LocalTime) where
58     {-# INLINE convertAttempt #-}
59     convertAttempt = parseAttempt' def
60
61 -- |Parse an ANSI C's date and time string.
62 instance Default (Parser (Tagged C LocalTime)) where
63     {-# INLINEABLE def #-}
64     def = do weekDay ← shortWeekDayNameP
65              _       ← char ' '
66              month   ← shortMonthNameP
67              _       ← char ' '
68              day     ← read2'
69              _       ← char ' '
70              hour    ← read2
71              _       ← char ':'
72              minute  ← read2
73              _       ← char ':'
74              second  ← read2
75              _       ← char ' '
76              year    ← read4
77
78              gregDay ← assertGregorianDateIsGood year month day
79              _       ← assertWeekDayIsGood weekDay gregDay
80              tod     ← assertTimeOfDayIsGood hour minute second
81
82              return ∘ Tagged $ LocalTime gregDay tod
83
84 toAsciiBuilder ∷ LocalTime → AsciiBuilder
85 toAsciiBuilder localTime
86     = let (year, month, day) = toGregorian (localDay localTime)
87           (_, _, week)       = toWeekDate  (localDay localTime)
88           timeOfDay          = localTimeOfDay localTime
89       in
90         shortWeekDayName week
91         ⊕ A.toAsciiBuilder " "
92         ⊕ shortMonthName month
93         ⊕ A.toAsciiBuilder " "
94         ⊕ show2' day
95         ⊕ A.toAsciiBuilder " "
96         ⊕ show2 (todHour timeOfDay)
97         ⊕ A.toAsciiBuilder ":"
98         ⊕ show2 (todMin timeOfDay)
99         ⊕ A.toAsciiBuilder ":"
100         ⊕ show2 (floor (todSec timeOfDay) ∷ Int)
101         ⊕ A.toAsciiBuilder " "
102         ⊕ show4 year
103
104 deriveAttempts [ ([t| Tagged C LocalTime |], [t| Ascii        |])
105                , ([t| Tagged C LocalTime |], [t| AsciiBuilder |])
106                ]