5 -- |This module provides functions for ANSI C's asctime() format.
7 -- ANSI C's asctime() format looks like:
9 -- @Wdy Mon [D]D HH:MM:SS YYYY@
11 -- The exact syntax is as follows:
13 -- > date-time ::= wday SP month SP day SP time SP year
14 -- > wday ::= "Mon" | "Tue" | "Wed" | "Thu"
15 -- > | "Fri" | "Sat" | "Sun"
16 -- > month ::= "Jan" | "Feb" | "Mar" | "Apr"
17 -- > | "May" | "Jun" | "Jul" | "Aug"
18 -- > | "Sep" | "Oct" | "Nov" | "Dec"
19 -- > day ::= 2DIGIT | SP 1DIGIT
20 -- > time ::= 2DIGIT ':' 2DIGIT [':' 2DIGIT]
23 -- As you can see, it has no time zone info. "Data.Time.HTTP" will
25 module Data.Time.Asctime
35 import Data.Ascii (Ascii, AsciiBuilder)
36 import qualified Data.Ascii as A
37 import Data.Attoparsec.Char8
38 import Data.Monoid.Unicode
40 import Data.Time.Calendar.WeekDate
41 import Data.Time.HTTP.Common
42 import Prelude.Unicode
44 -- |Convert a 'LocalTime' to ANSI C's @asctime()@ string.
45 toAscii ∷ LocalTime → Ascii
46 toAscii = A.fromAsciiBuilder ∘ toAsciiBuilder
48 -- |Parse an ANSI C's @asctime()@ string. When the string can't be
49 -- parsed, it returns @'Left' err@.
50 fromAscii ∷ Ascii → Either String LocalTime
51 fromAscii = parseOnly p ∘ A.toByteString
57 -- |Parse an ANSI C's @asctime()@ string.
58 asctime ∷ Parser LocalTime
59 asctime = do weekDay ← shortWeekDayNameP
61 month ← shortMonthNameP
73 gregDay ← assertGregorianDateIsGood year month day
74 _ ← assertWeekDayIsGood weekDay gregDay
75 tod ← assertTimeOfDayIsGood hour minute second
77 return (LocalTime gregDay tod)
79 -- |Convert a 'LocalTime' to ANSI C's @asctime()@ string.
80 toAsciiBuilder ∷ LocalTime → AsciiBuilder
81 toAsciiBuilder localTime
82 = let (year, month, day) = toGregorian (localDay localTime)
83 (_, _, week) = toWeekDate (localDay localTime)
84 timeOfDay = localTimeOfDay localTime
87 ⊕ A.toAsciiBuilder " "
88 ⊕ shortMonthName month
89 ⊕ A.toAsciiBuilder " "
91 ⊕ A.toAsciiBuilder " "
92 ⊕ show2 (todHour timeOfDay)
93 ⊕ A.toAsciiBuilder ":"
94 ⊕ show2 (todMin timeOfDay)
95 ⊕ A.toAsciiBuilder ":"
96 ⊕ show2 (floor (todSec timeOfDay) ∷ Int)
97 ⊕ A.toAsciiBuilder " "