@@ -63,6 +63,14 @@ This file implements string parsing and creation for NumPy datetime.
63
63
* to 0 otherwise. The values 'now' and 'today' don't get counted
64
64
* as local, and neither do UTC +/-#### timezone offsets, because
65
65
* they aren't using the computer's local timezone offset.
66
+ * 'exact' can be one of three values:
67
+ * * 0: don't require an exact match. For example, if the string
68
+ * is '2020-01-01 05:00:00' and format is '%Y-%m-%d', then
69
+ * parse '2020-01-01';
70
+ * * 1: require exact match. If the string is '2020-01-01', then
71
+ * the only format which will be able to parse it without
72
+ * error is '%Y-%m-%d';
73
+ * * 2: don't require any match.
66
74
*
67
75
* Returns 0 on success, -1 on failure.
68
76
*/
@@ -73,18 +81,8 @@ This file implements string parsing and creation for NumPy datetime.
73
81
static int compare_format (const char * * format , int * characters_remaining ,
74
82
const char * compare_to , int n , const int exact ) {
75
83
if (* characters_remaining < n ) {
76
- if (exact ) {
77
- // TODO(pandas-dev): in the future we should set a PyErr here
78
- // to be very clear about what went wrong
79
- return -1 ;
80
- } else if (* characters_remaining ) {
81
- // TODO(pandas-dev): same return value in this function as
82
- // above branch, but stub out a future where
83
- // we have a better error message
84
- return -1 ;
85
- } else {
86
- return 0 ;
87
- }
84
+ // TODO(pandas-dev): PyErr to differentiate what went wrong
85
+ return -1 ;
88
86
} else {
89
87
if (strncmp (* format , compare_to , n )) {
90
88
// TODO(pandas-dev): PyErr to differentiate what went wrong
@@ -139,8 +137,13 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
139
137
while (sublen > 0 && isspace (* substr )) {
140
138
++ substr ;
141
139
-- sublen ;
142
- if (compare_format (& format , & format_len , " " , 1 , exact )) {
143
- goto parse_error ;
140
+ if (exact != 2 ) {
141
+ if (exact == 0 && !format_len ) {
142
+ goto finish ;
143
+ }
144
+ if (compare_format (& format , & format_len , " " , 1 , exact )) {
145
+ goto parse_error ;
146
+ }
144
147
}
145
148
}
146
149
@@ -155,8 +158,13 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
155
158
}
156
159
157
160
/* PARSE THE YEAR (4 digits) */
158
- if (compare_format (& format , & format_len , "%Y" , 2 , exact )) {
159
- goto parse_error ;
161
+ if (exact != 2 ) {
162
+ if (exact == 0 && !format_len ) {
163
+ goto finish ;
164
+ }
165
+ if (compare_format (& format , & format_len , "%Y" , 2 , exact )) {
166
+ goto parse_error ;
167
+ }
160
168
}
161
169
162
170
out -> year = 0 ;
@@ -202,8 +210,13 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
202
210
++ substr ;
203
211
-- sublen ;
204
212
205
- if (compare_format (& format , & format_len , & ymd_sep , 1 , exact )) {
206
- goto parse_error ;
213
+ if (exact != 2 ) {
214
+ if (exact == 0 && !format_len ) {
215
+ goto finish ;
216
+ }
217
+ if (compare_format (& format , & format_len , & ymd_sep , 1 , exact )) {
218
+ goto parse_error ;
219
+ }
207
220
}
208
221
/* Cannot have trailing separator */
209
222
if (sublen == 0 || !isdigit (* substr )) {
@@ -212,8 +225,13 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
212
225
}
213
226
214
227
/* PARSE THE MONTH */
215
- if (compare_format (& format , & format_len , "%m" , 2 , exact )) {
216
- goto parse_error ;
228
+ if (exact != 2 ) {
229
+ if (exact == 0 && !format_len ) {
230
+ goto finish ;
231
+ }
232
+ if (compare_format (& format , & format_len , "%m" , 2 , exact )) {
233
+ goto parse_error ;
234
+ }
217
235
}
218
236
/* First digit required */
219
237
out -> month = (* substr - '0' );
@@ -258,14 +276,24 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
258
276
}
259
277
++ substr ;
260
278
-- sublen ;
261
- if (compare_format (& format , & format_len , & ymd_sep , 1 , exact )) {
262
- goto parse_error ;
279
+ if (exact != 2 ) {
280
+ if (exact == 0 && !format_len ) {
281
+ goto finish ;
282
+ }
283
+ if (compare_format (& format , & format_len , & ymd_sep , 1 , exact )) {
284
+ goto parse_error ;
285
+ }
263
286
}
264
287
}
265
288
266
289
/* PARSE THE DAY */
267
- if (compare_format (& format , & format_len , "%d" , 2 , exact )) {
268
- goto parse_error ;
290
+ if (exact != 2 ) {
291
+ if (exact == 0 && !format_len ) {
292
+ goto finish ;
293
+ }
294
+ if (compare_format (& format , & format_len , "%d" , 2 , exact )) {
295
+ goto parse_error ;
296
+ }
269
297
}
270
298
/* First digit required */
271
299
if (!isdigit (* substr )) {
@@ -306,15 +334,25 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
306
334
if ((* substr != 'T' && * substr != ' ' ) || sublen == 1 ) {
307
335
goto parse_error ;
308
336
}
309
- if (compare_format (& format , & format_len , substr , 1 , exact )) {
310
- goto parse_error ;
337
+ if (exact != 2 ) {
338
+ if (exact == 0 && !format_len ) {
339
+ goto finish ;
340
+ }
341
+ if (compare_format (& format , & format_len , substr , 1 , exact )) {
342
+ goto parse_error ;
343
+ }
311
344
}
312
345
++ substr ;
313
346
-- sublen ;
314
347
315
348
/* PARSE THE HOURS */
316
- if (compare_format (& format , & format_len , "%H" , 2 , exact )) {
317
- goto parse_error ;
349
+ if (exact != 2 ) {
350
+ if (exact == 0 && !format_len ) {
351
+ goto finish ;
352
+ }
353
+ if (compare_format (& format , & format_len , "%H" , 2 , exact )) {
354
+ goto parse_error ;
355
+ }
318
356
}
319
357
/* First digit required */
320
358
if (!isdigit (* substr )) {
@@ -359,8 +397,13 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
359
397
if (sublen == 0 || !isdigit (* substr )) {
360
398
goto parse_error ;
361
399
}
362
- if (compare_format (& format , & format_len , ":" , 1 , exact )) {
363
- goto parse_error ;
400
+ if (exact != 2 ) {
401
+ if (exact == 0 && !format_len ) {
402
+ goto finish ;
403
+ }
404
+ if (compare_format (& format , & format_len , ":" , 1 , exact )) {
405
+ goto parse_error ;
406
+ }
364
407
}
365
408
} else if (!isdigit (* substr )) {
366
409
if (!hour_was_2_digits ) {
@@ -370,8 +413,13 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
370
413
}
371
414
372
415
/* PARSE THE MINUTES */
373
- if (compare_format (& format , & format_len , "%M" , 2 , exact )) {
374
- goto parse_error ;
416
+ if (exact != 2 ) {
417
+ if (exact == 0 && !format_len ) {
418
+ goto finish ;
419
+ }
420
+ if (compare_format (& format , & format_len , "%M" , 2 , exact )) {
421
+ goto parse_error ;
422
+ }
375
423
}
376
424
/* First digit required */
377
425
out -> min = (* substr - '0' );
@@ -405,8 +453,13 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
405
453
/* If we make it through this condition block, then the next
406
454
* character is a digit. */
407
455
if (has_hms_sep && * substr == ':' ) {
408
- if (compare_format (& format , & format_len , ":" , 1 , exact )) {
409
- goto parse_error ;
456
+ if (exact != 2 ) {
457
+ if (exact == 0 && !format_len ) {
458
+ goto finish ;
459
+ }
460
+ if (compare_format (& format , & format_len , ":" , 1 , exact )) {
461
+ goto parse_error ;
462
+ }
410
463
}
411
464
++ substr ;
412
465
-- sublen ;
@@ -420,9 +473,14 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
420
473
}
421
474
422
475
/* PARSE THE SECONDS */
423
- if (compare_format (& format , & format_len , "%S" , 2 , exact )) {
424
- goto parse_error ;
425
- }
476
+ if (exact != 2 ) {
477
+ if (exact == 0 && !format_len ) {
478
+ goto finish ;
479
+ }
480
+ if (compare_format (& format , & format_len , "%S" , 2 , exact )) {
481
+ goto parse_error ;
482
+ }
483
+ }
426
484
/* First digit required */
427
485
out -> sec = (* substr - '0' );
428
486
++ substr ;
@@ -448,17 +506,27 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
448
506
if (sublen > 0 && * substr == '.' ) {
449
507
++ substr ;
450
508
-- sublen ;
451
- if (compare_format (& format , & format_len , "." , 1 , exact )) {
452
- goto parse_error ;
509
+ if (exact != 2 ) {
510
+ if (exact == 0 && !format_len ) {
511
+ goto finish ;
512
+ }
513
+ if (compare_format (& format , & format_len , "." , 1 , exact )) {
514
+ goto parse_error ;
515
+ }
453
516
}
454
517
} else {
455
518
bestunit = NPY_FR_s ;
456
519
goto parse_timezone ;
457
520
}
458
521
459
522
/* PARSE THE MICROSECONDS (0 to 6 digits) */
460
- if (compare_format (& format , & format_len , "%f" , 2 , exact )) {
461
- goto parse_error ;
523
+ if (exact != 2 ) {
524
+ if (exact == 0 && !format_len ) {
525
+ goto finish ;
526
+ }
527
+ if (compare_format (& format , & format_len , "%f" , 2 , exact )) {
528
+ goto parse_error ;
529
+ }
462
530
}
463
531
numdigits = 0 ;
464
532
for (i = 0 ; i < 6 ; ++ i ) {
@@ -524,8 +592,13 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
524
592
while (sublen > 0 && isspace (* substr )) {
525
593
++ substr ;
526
594
-- sublen ;
527
- if (compare_format (& format , & format_len , " " , 1 , exact )) {
528
- goto parse_error ;
595
+ if (exact != 2 ) {
596
+ if (exact == 0 && !format_len ) {
597
+ goto finish ;
598
+ }
599
+ if (compare_format (& format , & format_len , " " , 1 , exact )) {
600
+ goto parse_error ;
601
+ }
529
602
}
530
603
}
531
604
@@ -539,8 +612,13 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
539
612
540
613
/* UTC specifier */
541
614
if (* substr == 'Z' ) {
542
- if (compare_format (& format , & format_len , "%z" , 2 , exact )) {
543
- goto parse_error ;
615
+ if (exact != 2 ) {
616
+ if (exact == 0 && !format_len ) {
617
+ goto finish ;
618
+ }
619
+ if (compare_format (& format , & format_len , "%z" , 2 , exact )) {
620
+ goto parse_error ;
621
+ }
544
622
}
545
623
/* "Z" should be equivalent to tz offset "+00:00" */
546
624
if (out_local != NULL ) {
@@ -561,8 +639,13 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
561
639
-- sublen ;
562
640
}
563
641
} else if (* substr == '-' || * substr == '+' ) {
564
- if (compare_format (& format , & format_len , "%z" , 2 , exact )) {
565
- goto parse_error ;
642
+ if (exact != 2 ) {
643
+ if (exact == 0 && !format_len ) {
644
+ goto finish ;
645
+ }
646
+ if (compare_format (& format , & format_len , "%z" , 2 , exact )) {
647
+ goto parse_error ;
648
+ }
566
649
}
567
650
/* Time zone offset */
568
651
int offset_neg = 0 , offset_hour = 0 , offset_minute = 0 ;
@@ -647,8 +730,13 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
647
730
while (sublen > 0 && isspace (* substr )) {
648
731
++ substr ;
649
732
-- sublen ;
650
- if (compare_format (& format , & format_len , " " , 1 , exact )) {
651
- goto parse_error ;
733
+ if (exact != 2 ) {
734
+ if (exact == 0 && !format_len ) {
735
+ goto finish ;
736
+ }
737
+ if (compare_format (& format , & format_len , " " , 1 , exact )) {
738
+ goto parse_error ;
739
+ }
652
740
}
653
741
}
654
742
0 commit comments