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