23cf27a15895cbef65fab5e90fb5142139c0004f
[packages/time.git] / lib / Data / Time / Format / Parse.hs
1 {-# OPTIONS -fno-warn-orphans #-}
2 module Data.Time.Format.Parse
3 (
4 -- * UNIX-style parsing
5 parseTimeM, parseTimeOrError, readSTime, readPTime,
6 parseTime, readTime, readsTime,
7 ParseTime(),
8 -- * Locale
9 module Data.Time.Format.Locale
10 ) where
11
12 import Data.Proxy
13 #if MIN_VERSION_base(4,9,0)
14 import Control.Monad.Fail
15 import Prelude hiding (fail)
16 #endif
17 import Data.Char
18 import Data.Time.Format.Locale
19 import Text.ParserCombinators.ReadP hiding (char, string)
20 import Data.Time.Clock.Internal.UniversalTime
21 import Data.Time.Clock.Internal.UTCTime
22 import Data.Time.Calendar.Days
23 import Data.Time.LocalTime.Internal.TimeZone
24 import Data.Time.LocalTime.Internal.TimeOfDay
25 import Data.Time.LocalTime.Internal.LocalTime
26 import Data.Time.LocalTime.Internal.ZonedTime
27 import Data.Time.Format.Parse.Class
28 import Data.Time.Format.Parse.Instances()
29
30 -- | Parses a time value given a format string.
31 -- Supports the same %-codes as 'formatTime', including @%-@, @%_@ and @%0@ modifiers, however padding widths are not supported.
32 -- Case is not significant in the input string.
33 -- Some variations in the input are accepted:
34 --
35 -- [@%z@] accepts any of @±HHMM@ or @±HH:MM@.
36 --
37 -- [@%Z@] accepts any string of letters, or any of the formats accepted by @%z@.
38 --
39 -- [@%0Y@] accepts exactly four digits.
40 --
41 -- [@%0G@] accepts exactly four digits.
42 --
43 -- [@%0C@] accepts exactly two digits.
44 --
45 -- [@%0f@] accepts exactly two digits.
46 --
47 -- For example, to parse a date in YYYY-MM-DD format, while allowing the month
48 -- and date to have optional leading zeros (notice the @-@ modifier used for @%m@
49 -- and @%d@):
50 --
51 -- > Prelude Data.Time> parseTimeM True defaultTimeLocale "%Y-%-m-%-d" "2010-3-04" :: Maybe Day
52 -- > Just 2010-03-04
53 --
54 parseTimeM :: (
55 #if MIN_VERSION_base(4,9,0)
56 MonadFail m
57 #else
58 Monad m
59 #endif
60 ,ParseTime t) =>
61 Bool -- ^ Accept leading and trailing whitespace?
62 -> TimeLocale -- ^ Time locale.
63 -> String -- ^ Format string.
64 -> String -- ^ Input string.
65 -> m t -- ^ Return the time value, or fail if the input could
66 -- not be parsed using the given format.
67 parseTimeM acceptWS l fmt s = case parseTimeList acceptWS l fmt s of
68 [t] -> return t
69 [] -> fail $ "parseTimeM: no parse of " ++ show s
70 _ -> fail $ "parseTimeM: multiple parses of " ++ show s
71
72 -- | Parse a time value given a format string. Fails if the input could
73 -- not be parsed using the given format. See 'parseTimeM' for details.
74 parseTimeOrError :: ParseTime t =>
75 Bool -- ^ Accept leading and trailing whitespace?
76 -> TimeLocale -- ^ Time locale.
77 -> String -- ^ Format string.
78 -> String -- ^ Input string.
79 -> t -- ^ The time value.
80 parseTimeOrError acceptWS l fmt s = case parseTimeList acceptWS l fmt s of
81 [t] -> t
82 [] -> error $ "parseTimeOrError: no parse of " ++ show s
83 _ -> error $ "parseTimeOrError: multiple parses of " ++ show s
84
85 parseTimeList :: ParseTime t =>
86 Bool -- ^ Accept leading and trailing whitespace?
87 -> TimeLocale -- ^ Time locale.
88 -> String -- ^ Format string
89 -> String -- ^ Input string.
90 -> [t]
91 parseTimeList False l fmt s = [t | (t,"") <- readSTime False l fmt s]
92 parseTimeList True l fmt s = [t | (t,r) <- readSTime True l fmt s, all isSpace r]
93
94 -- | Parse a time value given a format string. See 'parseTimeM' for details.
95 readSTime :: ParseTime t =>
96 Bool -- ^ Accept leading whitespace?
97 -> TimeLocale -- ^ Time locale.
98 -> String -- ^ Format string
99 -> ReadS t
100 readSTime acceptWS l f = readP_to_S (readPTime acceptWS l f)
101
102 -- | Parse a time value given a format string. See 'parseTimeM' for details.
103 readPTime :: ParseTime t =>
104 Bool -- ^ Accept leading whitespace?
105 -> TimeLocale -- ^ Time locale.
106 -> String -- ^ Format string
107 -> ReadP t
108 readPTime False l f = readPOnlyTime l f
109 readPTime True l f = (skipSpaces >> readPOnlyTime l f) <++ readPOnlyTime l f
110
111 readPOnlyTime' :: ParseTime t => proxy t -> TimeLocale -> String -> ReadP t
112 readPOnlyTime' pt l f = do
113 pairs <- parseSpecifiers pt l f
114 case buildTime l pairs of
115 Just t -> return t
116 Nothing -> pfail
117
118 -- | Parse a time value given a format string (without allowing leading whitespace). See 'parseTimeM' for details.
119 readPOnlyTime :: ParseTime t =>
120 TimeLocale -- ^ Time locale.
121 -> String -- ^ Format string
122 -> ReadP t
123 readPOnlyTime = readPOnlyTime' Proxy
124
125 {-# DEPRECATED parseTime "use \"parseTimeM True\" instead" #-}
126 parseTime :: ParseTime t =>
127 TimeLocale -- ^ Time locale.
128 -> String -- ^ Format string.
129 -> String -- ^ Input string.
130 -> Maybe t -- ^ The time value, or 'Nothing' if the input could
131 -- not be parsed using the given format.
132 parseTime = parseTimeM True
133
134 {-# DEPRECATED readTime "use \"parseTimeOrError True\" instead" #-}
135 readTime :: ParseTime t =>
136 TimeLocale -- ^ Time locale.
137 -> String -- ^ Format string.
138 -> String -- ^ Input string.
139 -> t -- ^ The time value.
140 readTime = parseTimeOrError True
141
142 {-# DEPRECATED readsTime "use \"readSTime True\" instead" #-}
143 readsTime :: ParseTime t =>
144 TimeLocale -- ^ Time locale.
145 -> String -- ^ Format string
146 -> ReadS t
147 readsTime = readSTime True
148
149 -- * Read instances for time package types
150
151 instance Read Day where
152 readsPrec _ = readParen False $ readSTime True defaultTimeLocale "%Y-%m-%d"
153
154 instance Read TimeOfDay where
155 readsPrec _ = readParen False $ readSTime True defaultTimeLocale "%H:%M:%S%Q"
156
157 instance Read LocalTime where
158 readsPrec _ = readParen False $ readSTime True defaultTimeLocale "%Y-%m-%d %H:%M:%S%Q"
159
160 -- | This only works for @±HHMM@ format,
161 -- single-letter military time-zones,
162 -- and these time-zones: \"UTC\", \"UT\", \"GMT\", \"EST\", \"EDT\", \"CST\", \"CDT\", \"MST\", \"MDT\", \"PST\", \"PDT\".
163 instance Read TimeZone where
164 readsPrec _ = readParen False $ readSTime True defaultTimeLocale "%Z"
165
166 -- | This only works for a 'zonedTimeZone' in @±HHMM@ format,
167 -- single-letter military time-zones,
168 -- and these time-zones: \"UTC\", \"UT\", \"GMT\", \"EST\", \"EDT\", \"CST\", \"CDT\", \"MST\", \"MDT\", \"PST\", \"PDT\".
169 instance Read ZonedTime where
170 readsPrec n = readParen False $ \s ->
171 [(ZonedTime t z, r2) | (t,r1) <- readsPrec n s, (z,r2) <- readsPrec n r1]
172
173 instance Read UTCTime where
174 readsPrec n s = [ (zonedTimeToUTC t, r) | (t,r) <- readsPrec n s ]
175
176 instance Read UniversalTime where
177 readsPrec n s = [ (localTimeToUT1 0 t, r) | (t,r) <- readsPrec n s ]