@@ -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,62 +200,76 @@ 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))
255
-
256
- j > end_pos || @goto error
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
+ j > end_pos || @goto error
272
+ end
257
273
258
274
@label done
259
275
return DateTime (dy, dm, dd, th, tm, ts, tms)
@@ -264,21 +280,22 @@ end
264
280
265
281
function Base. parse (:: Type{T} , str:: AbstractString , df:: DateFormat = default_format (T)) where T<: TimeType
266
282
pos, len = firstindex (str), lastindex (str)
267
- values, pos = tryparsenext_internal (T, str, pos, len, df, true )
268
- T (values... )
283
+ val = tryparsenext_internal (T, str, pos, len, df, true )
284
+ @assert val != = nothing
285
+ values, endpos = val
286
+ return T (values... )
269
287
end
270
288
271
289
function Base. tryparse (:: Type{T} , str:: AbstractString , df:: DateFormat = default_format (T)) where T<: TimeType
272
290
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
291
+ res = tryparsenext_internal (T, str, pos, len, df, false )
292
+ res === nothing && return nothing
293
+ values, endpos = res
294
+ if validargs (T, values... ) === nothing
277
295
# TODO : validargs gets called twice, since it's called again in the T constructor
278
- T (values... )
279
- else
280
- nothing
296
+ return T (values... )
281
297
end
298
+ return nothing
282
299
end
283
300
284
301
"""
@@ -293,15 +310,16 @@ number of components may be less than the total number of `DatePart`.
293
310
letters = character_codes (df)
294
311
tokens = Type[CONVERSION_SPECIFIERS[letter] for letter in letters]
295
312
296
- quote
313
+ return quote
297
314
pos, len = firstindex (str), lastindex (str)
298
- values, pos, num_parsed = tryparsenext_core (str, pos, len, df, true )
299
- t = values
315
+ val = tryparsenext_core (str, pos, len, df, #= raise=# true )
316
+ @assert val != = nothing
317
+ values, pos, num_parsed = val
300
318
types = $ (Expr (:tuple , tokens... ))
301
319
result = Vector {Any} (undef, num_parsed)
302
320
for (i, typ) in enumerate (types)
303
321
i > num_parsed && break
304
- result[i] = typ (t [i]) # Constructing types takes most of the time
322
+ result[i] = typ (values [i]) # Constructing types takes most of the time
305
323
end
306
324
return result
307
325
end
0 commit comments