1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ViewPatterns #-}
module TimeUtil
( now
, IsTime(..)
, parseRFC2822
, printRFC2822
) where
import Data.Time.LocalTime
import Data.Time.Format
import Data.Time.Clock
import Data.Time.Clock.POSIX
import System.Locale
import Data.String
import Control.Applicative
import Data.Maybe
import Data.Char
import qualified Data.ByteString.Char8 as S
class IsTime a where
fromZonedTime :: ZonedTime -> a
toZonedTime :: a -> IO ZonedTime
instance IsTime ZonedTime where
fromZonedTime x = x
toZonedTime x = return x
instance IsTime UTCTime where
toZonedTime t = utcToLocalZonedTime t
fromZonedTime zt = zonedTimeToUTC zt
instance IsTime Integer where
toZonedTime t = utcToLocalZonedTime utime
where
utime = posixSecondsToUTCTime (fromIntegral t)
fromZonedTime zt = round $ utcTimeToPOSIXSeconds utime
where
utime = zonedTimeToUTC zt
printRFC2822 :: (IsString b, IsTime a) => a -> IO b
printRFC2822 tm = do
zt@(ZonedTime lt z) <- toZonedTime tm
let rfc2822 = formatTime defaultTimeLocale "%a, %0e %b %Y %T" zt ++ printZone
timeZoneStr = timeZoneOffsetString z
printZone = " " ++ timeZoneStr ++ " (" ++ fromString (show z) ++ ")"
return $ fromString $ rfc2822
parseRFC2822 :: IsTime b => S.ByteString -> Maybe b
parseRFC2822 str =
case mapMaybe (\f->parseTime defaultTimeLocale f str') formatRFC2822 of
[] -> Nothing
(zt:_) -> Just $ fromZonedTime zt
where
str' = S.unpack stripped
stripped = strip $ str
strip bs = bs3
where
(_,bs0) = S.span isSpace bs
(bs1,_) = S.spanEnd isSpace bs0
(bs2,cp) = S.spanEnd (==')') bs1
bs3 = if S.null cp
then bs2
else let (op,_) = S.spanEnd (/='(') bs2
in fst $ S.spanEnd isSpace $ S.init op
formatRFC2822 = [ "%a, %e %b %Y %T GMT"
, "%a, %e %b %Y %T %z"
, "%e %b %Y %T GMT"
, "%e %b %Y %T %z"
, "%a, %e %b %Y %R GMT"
, "%a, %e %b %Y %R %z"
, "%e %b %Y %R GMT"
, "%e %b %Y %R %z"
]
now :: IO Integer
now = floor <$> Data.Time.Clock.POSIX.getPOSIXTime
{-
main = do
nowtime <- now
printRFC2822 nowtime >>= putStrLn
let test1 = "Thu, 08 May 2014 23:24:47 -0400"
test2 = " Thu, 08 May 2014 23:24:47 -0400 (EDT) "
putStrLn $ show (parseRFC2822 test1 :: Maybe Integer)
putStrLn $ show (parseRFC2822 test2 :: Maybe Integer)
return ()
-}
|