@@ -69,7 +69,9 @@ This file implements string parsing and creation for NumPy datetime.
69
69
int parse_iso_8601_datetime (const char * str , int len , int want_exc ,
70
70
npy_datetimestruct * out ,
71
71
NPY_DATETIMEUNIT * out_bestunit ,
72
- int * out_local , int * out_tzoffset ) {
72
+ int * out_local , int * out_tzoffset ,
73
+ char * inferred_format , int * format_len ) {
74
+ int fmt_idx = 0 ;
73
75
int year_leap = 0 ;
74
76
int i , numdigits ;
75
77
const char * substr ;
@@ -104,6 +106,8 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
104
106
while (sublen > 0 && isspace (* substr )) {
105
107
++ substr ;
106
108
-- sublen ;
109
+ inferred_format [fmt_idx ] = ' ' ;
110
+ ++ fmt_idx ;
107
111
}
108
112
109
113
/* Leading '-' sign for negative year */
@@ -125,6 +129,10 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
125
129
126
130
substr += 4 ;
127
131
sublen -= 4 ;
132
+ inferred_format [fmt_idx ] = '%' ;
133
+ ++ fmt_idx ;
134
+ inferred_format [fmt_idx ] = 'Y' ;
135
+ ++ fmt_idx ;
128
136
}
129
137
130
138
/* Negate the year if necessary */
@@ -156,6 +164,8 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
156
164
ymd_sep = valid_ymd_sep [i ];
157
165
++ substr ;
158
166
-- sublen ;
167
+ inferred_format [fmt_idx ] = ymd_sep ;
168
+ ++ fmt_idx ;
159
169
/* Cannot have trailing separator */
160
170
if (sublen == 0 || !isdigit (* substr )) {
161
171
goto parse_error ;
@@ -183,6 +193,11 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
183
193
goto error ;
184
194
}
185
195
196
+ inferred_format [fmt_idx ] = '%' ;
197
+ ++ fmt_idx ;
198
+ inferred_format [fmt_idx ] = 'm' ;
199
+ ++ fmt_idx ;
200
+
186
201
/* Next character must be the separator, start of day, or end of string */
187
202
if (sublen == 0 ) {
188
203
bestunit = NPY_FR_M ;
@@ -201,6 +216,8 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
201
216
if (* substr != ymd_sep || sublen == 1 ) {
202
217
goto parse_error ;
203
218
}
219
+ inferred_format [fmt_idx ] = * substr ;
220
+ ++ fmt_idx ;
204
221
++ substr ;
205
222
-- sublen ;
206
223
}
@@ -230,6 +247,11 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
230
247
goto error ;
231
248
}
232
249
250
+ inferred_format [fmt_idx ] = '%' ;
251
+ ++ fmt_idx ;
252
+ inferred_format [fmt_idx ] = 'd' ;
253
+ ++ fmt_idx ;
254
+
233
255
/* Next character must be a 'T', ' ', or end of string */
234
256
if (sublen == 0 ) {
235
257
if (out_local != NULL ) {
@@ -242,6 +264,8 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
242
264
if ((* substr != 'T' && * substr != ' ' ) || sublen == 1 ) {
243
265
goto parse_error ;
244
266
}
267
+ inferred_format [fmt_idx ] = * substr ;
268
+ ++ fmt_idx ;
245
269
++ substr ;
246
270
-- sublen ;
247
271
@@ -269,6 +293,11 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
269
293
}
270
294
}
271
295
296
+ inferred_format [fmt_idx ] = '%' ;
297
+ ++ fmt_idx ;
298
+ inferred_format [fmt_idx ] = 'H' ;
299
+ ++ fmt_idx ;
300
+
272
301
/* Next character must be a ':' or the end of the string */
273
302
if (sublen == 0 ) {
274
303
if (!hour_was_2_digits ) {
@@ -279,6 +308,8 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
279
308
}
280
309
281
310
if (* substr == ':' ) {
311
+ inferred_format [fmt_idx ] = ':' ;
312
+ ++ fmt_idx ;
282
313
has_hms_sep = 1 ;
283
314
++ substr ;
284
315
-- sublen ;
@@ -315,6 +346,11 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
315
346
goto parse_error ;
316
347
}
317
348
349
+ inferred_format [fmt_idx ] = '%' ;
350
+ ++ fmt_idx ;
351
+ inferred_format [fmt_idx ] = 'M' ;
352
+ ++ fmt_idx ;
353
+
318
354
if (sublen == 0 ) {
319
355
bestunit = NPY_FR_m ;
320
356
goto finish ;
@@ -323,6 +359,8 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
323
359
/* If we make it through this condition block, then the next
324
360
* character is a digit. */
325
361
if (has_hms_sep && * substr == ':' ) {
362
+ inferred_format [fmt_idx ] = ':' ;
363
+ ++ fmt_idx ;
326
364
++ substr ;
327
365
-- sublen ;
328
366
/* Cannot have a trailing ':' */
@@ -356,15 +394,27 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
356
394
goto parse_error ;
357
395
}
358
396
397
+ inferred_format [fmt_idx ] = '%' ;
398
+ ++ fmt_idx ;
399
+ inferred_format [fmt_idx ] = 'S' ;
400
+ ++ fmt_idx ;
401
+
359
402
/* Next character may be a '.' indicating fractional seconds */
360
403
if (sublen > 0 && * substr == '.' ) {
361
404
++ substr ;
362
405
-- sublen ;
406
+ inferred_format [fmt_idx ] = '.' ;
407
+ ++ fmt_idx ;
363
408
} else {
364
409
bestunit = NPY_FR_s ;
365
410
goto parse_timezone ;
366
411
}
367
412
413
+ inferred_format [fmt_idx ] = '%' ;
414
+ ++ fmt_idx ;
415
+ inferred_format [fmt_idx ] = 'f' ;
416
+ ++ fmt_idx ;
417
+
368
418
/* PARSE THE MICROSECONDS (0 to 6 digits) */
369
419
numdigits = 0 ;
370
420
for (i = 0 ; i < 6 ; ++ i ) {
@@ -430,6 +480,8 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
430
480
while (sublen > 0 && isspace (* substr )) {
431
481
++ substr ;
432
482
-- sublen ;
483
+ inferred_format [fmt_idx ] = ' ' ;
484
+ ++ fmt_idx ;
433
485
}
434
486
435
487
if (sublen == 0 ) {
@@ -439,6 +491,10 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
439
491
440
492
/* UTC specifier */
441
493
if (* substr == 'Z' ) {
494
+ inferred_format [fmt_idx ] = '%' ;
495
+ ++ fmt_idx ;
496
+ inferred_format [fmt_idx ] = 'Z' ;
497
+ ++ fmt_idx ;
442
498
/* "Z" should be equivalent to tz offset "+00:00" */
443
499
if (out_local != NULL ) {
444
500
* out_local = 1 ;
@@ -455,6 +511,10 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
455
511
-- sublen ;
456
512
}
457
513
} else if (* substr == '-' || * substr == '+' ) {
514
+ inferred_format [fmt_idx ] = '%' ;
515
+ ++ fmt_idx ;
516
+ inferred_format [fmt_idx ] = 'z' ;
517
+ ++ fmt_idx ;
458
518
/* Time zone offset */
459
519
int offset_neg = 0 , offset_hour = 0 , offset_minute = 0 ;
460
520
@@ -538,6 +598,8 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
538
598
while (sublen > 0 && isspace (* substr )) {
539
599
++ substr ;
540
600
-- sublen ;
601
+ inferred_format [fmt_idx ] = ' ' ;
602
+ ++ fmt_idx ;
541
603
}
542
604
543
605
if (sublen != 0 ) {
@@ -548,6 +610,7 @@ int parse_iso_8601_datetime(const char *str, int len, int want_exc,
548
610
if (out_bestunit != NULL ) {
549
611
* out_bestunit = bestunit ;
550
612
}
613
+ * format_len = fmt_idx ;
551
614
return 0 ;
552
615
553
616
parse_error :
0 commit comments