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