@@ -23,11 +23,11 @@ genvar(t::DataType) = Symbol(lowercase(string(nameof(t))))
23
23
24
24
Parse the string according to the directives within the `DateFormat`. Parsing will start at
25
25
character index `pos` and will stop when all directives are used or we have parsed up to
26
- the end of the string, `len`. When a directive cannot be parsed the returned value tuple
26
+ the end of the string, `len`. When a directive cannot be parsed the returned value
27
27
will be `nothing` if `raise` is false otherwise an exception will be thrown.
28
28
29
- Return a 3-element tuple `(values, pos, num_parsed)`:
30
- * `values::Union{ Tuple, Nothing} `: Either `nothing`, or a tuple which contains a value
29
+ If successful, return a 3-element tuple `(values, pos, num_parsed)`:
30
+ * `values::Tuple`: A tuple which contains a value
31
31
for each `DatePart` within the `DateFormat` in the order
32
32
in which they occur. If the string ends before we finish parsing all the directives
33
33
the missing values will be filled in with default values.
@@ -58,29 +58,30 @@ Return a 3-element tuple `(values, pos, num_parsed)`:
58
58
for i = 1 : length (directives)
59
59
if directives[i] <: DatePart
60
60
name = value_names[vi]
61
- val = Symbol (:val , name)
62
61
vi += 1
63
62
push! (parsers, quote
64
63
pos > len && @goto done
65
- $ val, next_pos = tryparsenext (directives[$ i], str, pos, len, locale)
66
- $ val === nothing && @goto error
67
- $ name = $ val
68
- pos = next_pos
64
+ local $ name
65
+ let val = tryparsenext (directives[$ i], str, pos, len, locale)
66
+ val === nothing && @goto error
67
+ $ name, pos = val
68
+ end
69
69
num_parsed += 1
70
70
directive_index += 1
71
71
end )
72
72
else
73
73
push! (parsers, quote
74
74
pos > len && @goto done
75
- delim, next_pos = tryparsenext (directives[$ i], str, pos, len, locale)
76
- delim === nothing && @goto error
77
- pos = next_pos
75
+ let val = tryparsenext (directives[$ i], str, pos, len, locale)
76
+ val === nothing && @goto error
77
+ delim, pos = val
78
+ end
78
79
directive_index += 1
79
80
end )
80
81
end
81
82
end
82
83
83
- quote
84
+ return quote
84
85
directives = df. tokens
85
86
locale:: DateLocale = df. locale
86
87
@@ -104,7 +105,7 @@ Return a 3-element tuple `(values, pos, num_parsed)`:
104
105
throw (ArgumentError (" Unable to parse date time. Expected directive $d at char $pos " ))
105
106
end
106
107
end
107
- return nothing , pos, 0
108
+ return nothing
108
109
end
109
110
end
110
111
@@ -114,11 +115,11 @@ end
114
115
Parse the string according to the directives within the `DateFormat`. The specified `TimeType`
115
116
type determines the type of and order of tokens returned. If the given `DateFormat` or string
116
117
does not provide a required token a default value will be used. When the string cannot be
117
- parsed the returned value tuple will be `nothing` if `raise` is false otherwise an exception will
118
+ parsed the returned value will be `nothing` if `raise` is false otherwise an exception will
118
119
be thrown.
119
120
120
- Return a 2-element tuple `(values, pos)`:
121
- * `values::Union{ Tuple, Nothing} `: Either `nothing`, or a tuple which contains a value
121
+ If successful, returns a 2-element tuple `(values, pos)`:
122
+ * `values::Tuple`: A tuple which contains a value
122
123
for each token as specified by the passed in type.
123
124
* `pos::Int`: The character index at which parsing stopped.
124
125
"""
@@ -146,17 +147,18 @@ Return a 2-element tuple `(values, pos)`:
146
147
# Unpacks the value tuple returned by `tryparsenext_core` into separate variables.
147
148
value_tuple = Expr (:tuple , value_names... )
148
149
149
- quote
150
- values, pos, num_parsed = tryparsenext_core (str, pos, len, df, raise)
151
- values === nothing && return nothing , pos
150
+ return quote
151
+ val = tryparsenext_core (str, pos, len, df, raise)
152
+ val === nothing && return nothing
153
+ values, pos, num_parsed = val
152
154
$ (assign_defaults... )
153
155
$ value_tuple = values
154
156
return $ (Expr (:tuple , output_names... )), pos
155
157
end
156
158
end
157
159
158
160
@inline function tryparsenext_base10 (str:: AbstractString , i:: Int , len:: Int , min_width:: Int = 1 , max_width:: Int = 0 )
159
- i > len && ( return nothing , i)
161
+ i > len && return nothing
160
162
min_pos = min_width <= 0 ? i : i + min_width - 1
161
163
max_pos = max_width <= 0 ? len : min (i + max_width - 1 , len)
162
164
d:: Int64 = 0
170
172
i = ii
171
173
end
172
174
if i <= min_pos
173
- return nothing , i
175
+ return nothing
174
176
else
175
177
return d, i
176
178
end
189
191
i = ii
190
192
end
191
193
if word_end == 0
192
- return nothing , i
194
+ return nothing
193
195
else
194
196
return SubString (str, word_start, word_end), i
195
197
end
@@ -198,60 +200,75 @@ end
198
200
function Base. parse (:: Type{DateTime} , s:: AbstractString , df:: typeof (ISODateTimeFormat))
199
201
i, end_pos = firstindex (s), lastindex (s)
200
202
203
+ local dy
201
204
dm = dd = Int64 (1 )
202
205
th = tm = ts = tms = Int64 (0 )
203
206
204
- val, i = tryparsenext_base10 (s, i, end_pos, 1 )
205
- dy = val === nothing ? (@goto error) : val
206
- i > end_pos && @goto error
207
+ let val = tryparsenext_base10 (s, i, end_pos, 1 )
208
+ val === nothing && @goto error
209
+ dy, i = val
210
+ i > end_pos && @goto error
211
+ end
207
212
208
213
c, i = next (s, i)
209
214
c != ' -' && @goto error
210
215
i > end_pos && @goto done
211
216
212
- val, i = tryparsenext_base10 (s, i, end_pos, 1 , 2 )
213
- dm = val === nothing ? (@goto error) : val
214
- i > end_pos && @goto done
217
+ let val = tryparsenext_base10 (s, i, end_pos, 1 , 2 )
218
+ val === nothing && @goto error
219
+ dm, i = val
220
+ i > end_pos && @goto done
221
+ end
215
222
216
223
c, i = next (s, i)
217
224
c != ' -' && @goto error
218
225
i > end_pos && @goto done
219
226
220
- val, i = tryparsenext_base10 (s, i, end_pos, 1 , 2 )
221
- dd = val === nothing ? (@goto error) : val
222
- i > end_pos && @goto done
227
+ let val = tryparsenext_base10 (s, i, end_pos, 1 , 2 )
228
+ val === nothing && @goto error
229
+ dd, i = val
230
+ i > end_pos && @goto done
231
+ end
223
232
224
233
c, i = next (s, i)
225
234
c != ' T' && @goto error
226
235
i > end_pos && @goto done
227
236
228
- val, i = tryparsenext_base10 (s, i, end_pos, 1 , 2 )
229
- th = val === nothing ? (@goto error) : val
230
- i > end_pos && @goto done
237
+ let val = tryparsenext_base10 (s, i, end_pos, 1 , 2 )
238
+ val === nothing && @goto error
239
+ th, i = val
240
+ i > end_pos && @goto done
241
+ end
231
242
232
243
c, i = next (s, i)
233
244
c != ' :' && @goto error
234
245
i > end_pos && @goto done
235
246
236
- val, i = tryparsenext_base10 (s, i, end_pos, 1 , 2 )
237
- tm = val === nothing ? (@goto error) : val
238
- i > end_pos && @goto done
247
+ let val = tryparsenext_base10 (s, i, end_pos, 1 , 2 )
248
+ val === nothing && @goto error
249
+ tm, i = val
250
+ i > end_pos && @goto done
251
+ end
239
252
240
253
c, i = next (s, i)
241
254
c != ' :' && @goto error
242
255
i > end_pos && @goto done
243
256
244
- val, i = tryparsenext_base10 (s, i, end_pos, 1 , 2 )
245
- ts = val === nothing ? (@goto error) : val
246
- i > end_pos && @goto done
257
+ let val = tryparsenext_base10 (s, i, end_pos, 1 , 2 )
258
+ val === nothing && @goto error
259
+ ts, i = val
260
+ i > end_pos && @goto done
261
+ end
247
262
248
263
c, i = next (s, i)
249
264
c != ' .' && @goto error
250
265
i > end_pos && @goto done
251
266
252
- val, j = tryparsenext_base10 (s, i, end_pos, 1 , 3 )
253
- tms = val === nothing ? (@goto error) : val
254
- tms *= 10 ^ (3 - (j - i))
267
+ let val = tryparsenext_base10 (s, i, end_pos, 1 , 3 )
268
+ val === nothing && @goto error
269
+ tms, j = val
270
+ tms *= 10 ^ (3 - (j - i))
271
+ end
255
272
256
273
j > end_pos || @goto error
257
274
@@ -264,21 +281,22 @@ end
264
281
265
282
function Base. parse (:: Type{T} , str:: AbstractString , df:: DateFormat = default_format (T)) where T<: TimeType
266
283
pos, len = firstindex (str), lastindex (str)
267
- values, pos = tryparsenext_internal (T, str, pos, len, df, true )
268
- T (values... )
284
+ val = tryparsenext_internal (T, str, pos, len, df, true )
285
+ @assert val != = nothing
286
+ values, endpos = val
287
+ return T (values... )
269
288
end
270
289
271
290
function Base. tryparse (:: Type{T} , str:: AbstractString , df:: DateFormat = default_format (T)) where T<: TimeType
272
291
pos, len = firstindex (str), lastindex (str)
273
- values, pos = tryparsenext_internal (T, str, pos, len, df, false )
274
- if values === nothing
275
- nothing
276
- elseif validargs (T, values... ) === nothing
292
+ res = tryparsenext_internal (T, str, pos, len, df, false )
293
+ res === nothing && return nothing
294
+ values, endpos = res
295
+ if validargs (T, values... ) === nothing
277
296
# TODO : validargs gets called twice, since it's called again in the T constructor
278
- T (values... )
279
- else
280
- nothing
297
+ return T (values... )
281
298
end
299
+ return nothing
282
300
end
283
301
284
302
"""
@@ -293,15 +311,16 @@ number of components may be less than the total number of `DatePart`.
293
311
letters = character_codes (df)
294
312
tokens = Type[CONVERSION_SPECIFIERS[letter] for letter in letters]
295
313
296
- quote
314
+ return quote
297
315
pos, len = firstindex (str), lastindex (str)
298
- values, pos, num_parsed = tryparsenext_core (str, pos, len, df, true )
299
- t = values
316
+ val = tryparsenext_core (str, pos, len, df, #= raise=# true )
317
+ @assert val != = nothing
318
+ values, pos, num_parsed = val
300
319
types = $ (Expr (:tuple , tokens... ))
301
320
result = Vector {Any} (undef, num_parsed)
302
321
for (i, typ) in enumerate (types)
303
322
i > num_parsed && break
304
- result[i] = typ (t [i]) # Constructing types takes most of the time
323
+ result[i] = typ (values [i]) # Constructing types takes most of the time
305
324
end
306
325
return result
307
326
end
0 commit comments