-{-# LANGUAGE
- FlexibleInstances
- , MultiParamTypeClasses
- , OverloadedStrings
- , TemplateHaskell
- , UnicodeSyntax
- #-}
--- |This module provides functions for ANSI C's asctime() format.
---
--- ANSI C's asctime() format looks like:
---
--- @Wdy Mon [D]D HH:MM:SS YYYY@
---
--- The exact syntax is as follows:
---
--- > date-time ::= wday SP month SP day SP time SP year
--- > wday ::= "Mon" | "Tue" | "Wed" | "Thu"
--- > | "Fri" | "Sat" | "Sun"
--- > month ::= "Jan" | "Feb" | "Mar" | "Apr"
--- > | "May" | "Jun" | "Jul" | "Aug"
--- > | "Sep" | "Oct" | "Nov" | "Dec"
--- > day ::= 2DIGIT | SP 1DIGIT
--- > time ::= 2DIGIT ':' 2DIGIT [':' 2DIGIT]
--- > year ::= 4DIGIT
---
--- As you can see, it has no time zone info. "Data.Time.HTTP" will
--- treat it as UTC.
-module Data.Time.Asctime
- ( Asctime
- , asctime
- )
- where
-import Control.Applicative
-import Data.Ascii (Ascii, AsciiBuilder)
-import qualified Data.Ascii as A
-import Data.Attoparsec.Char8
-import Data.Convertible.Base
-import Data.Monoid.Unicode
-import Data.Tagged
-import Data.Time
-import Data.Time.Calendar.WeekDate
-import Data.Time.HTTP.Common
-import Prelude.Unicode
-
--- |The phantom type for conversion between ANSI C's @asctime()@
--- string and 'LocalTime'.
---
--- >>> convertSuccess (LocalTime (ModifiedJulianDay 49662) (TimeOfDay 8 49 37))
--- Tagged "Sun Nov 6 08:49:37 1994"
-data Asctime
-
-instance ConvertSuccess LocalTime (Tagged Asctime Ascii) where
- {-# INLINE convertSuccess #-}
- convertSuccess = (A.fromAsciiBuilder <$>) ∘ cs
-
-instance ConvertSuccess LocalTime (Tagged Asctime AsciiBuilder) where
- {-# INLINE convertSuccess #-}
- convertSuccess = Tagged ∘ toAsciiBuilder
-
-instance ConvertAttempt (Tagged Asctime Ascii) LocalTime where
- {-# INLINE convertAttempt #-}
- convertAttempt = parseAttempt' asctime ∘ untag
-
--- |Parse an ANSI C's @asctime()@ string.
-asctime ∷ Parser LocalTime
-asctime = do weekDay ← shortWeekDayNameP
- _ ← char ' '
- month ← shortMonthNameP
- _ ← char ' '
- day ← read2'
- _ ← char ' '
- hour ← read2
- _ ← char ':'
- minute ← read2
- _ ← char ':'
- second ← read2
- _ ← char ' '
- year ← read4
-
- gregDay ← assertGregorianDateIsGood year month day
- _ ← assertWeekDayIsGood weekDay gregDay
- tod ← assertTimeOfDayIsGood hour minute second
-
- return (LocalTime gregDay tod)
-
-toAsciiBuilder ∷ LocalTime → AsciiBuilder
-toAsciiBuilder localTime
- = let (year, month, day) = toGregorian (localDay localTime)
- (_, _, week) = toWeekDate (localDay localTime)
- timeOfDay = localTimeOfDay localTime
- in
- shortWeekDayName week
- ⊕ A.toAsciiBuilder " "
- ⊕ shortMonthName month
- ⊕ A.toAsciiBuilder " "
- ⊕ show2' day
- ⊕ A.toAsciiBuilder " "
- ⊕ show2 (todHour timeOfDay)
- ⊕ A.toAsciiBuilder ":"
- ⊕ show2 (todMin timeOfDay)
- ⊕ A.toAsciiBuilder ":"
- ⊕ show2 (floor (todSec timeOfDay) ∷ Int)
- ⊕ A.toAsciiBuilder " "
- ⊕ show4 year
-
-deriveAttempts [ ([t| LocalTime |], [t| Tagged Asctime Ascii |])
- , ([t| LocalTime |], [t| Tagged Asctime AsciiBuilder |])
- ]