-- |This module provides functions for ANSI C's asctime() format.
--
-- ANSI C's asctime() format looks like:
--
-- @Wdy Mon DD 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
-- > 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
    ( format
    , parse
    )
    where

import qualified Text.Parsec as P

import Data.Time
import Data.Time.Calendar.WeekDate
import Data.Time.HTTP.Common
import Data.Time.Asctime.Parsec

-- |Format a 'LocalTime' in the ANSI C's asctime() way.
format :: LocalTime -> String
format localTime
    = let (year, month, day) = toGregorian (localDay localTime)
          (_, _, week)       = toWeekDate  (localDay localTime)
          timeOfDay          = localTimeOfDay localTime
      in
        concat [ shortWeekDayName week
               , ", "
               , shortMonthName month
               , " "
               , show2 day
               , " "
               , show2 (todHour timeOfDay)
               , ":"
               , show2 (todMin timeOfDay)
               , ":"
               , show2 (floor (todSec timeOfDay))
               , " "
               , show4 year
               ]

-- |Parse an ANSI C's asctime() format to 'LocalTime'. When the string
-- can't be parsed, it returns 'Nothing'.
parse :: String -> Maybe LocalTime
parse src = case P.parse p "" src of
              Right zt -> Just zt
              Left  _  -> Nothing
    where
      p = do zt <- asctime
             _  <- P.eof
             return zt