@@ -493,6 +493,12 @@ static int match_alpha(const char *date, struct tm *tm, int *offset)
493
493
return 2 ;
494
494
}
495
495
496
+ /* ISO-8601 allows yyyymmDD'T'HHMMSS, with less precision */
497
+ if (* date == 'T' && isdigit (date [1 ]) && tm -> tm_hour == -1 ) {
498
+ tm -> tm_min = tm -> tm_sec = 0 ;
499
+ return 1 ;
500
+ }
501
+
496
502
/* BAD CRAP */
497
503
return skip_alpha (date );
498
504
}
@@ -638,6 +644,18 @@ static inline int nodate(struct tm *tm)
638
644
tm -> tm_sec ) < 0 ;
639
645
}
640
646
647
+ /*
648
+ * Have we seen an ISO-8601-alike date, i.e. 20220101T0,
649
+ * In which, hour is still unset,
650
+ * and minutes and second has been set to 0.
651
+ */
652
+ static inline int maybeiso8601 (struct tm * tm )
653
+ {
654
+ return tm -> tm_hour == -1 &&
655
+ tm -> tm_min == 0 &&
656
+ tm -> tm_sec == 0 ;
657
+ }
658
+
641
659
/*
642
660
* We've seen a digit. Time? Year? Date?
643
661
*/
@@ -701,6 +719,25 @@ static int match_digit(const char *date, struct tm *tm, int *offset, int *tm_gmt
701
719
return end - date ;
702
720
}
703
721
722
+ /* reduced precision of ISO-8601's time: HHMM or HH */
723
+ if (maybeiso8601 (tm )) {
724
+ unsigned int num1 = num ;
725
+ unsigned int num2 = 0 ;
726
+ if (n == 4 ) {
727
+ num1 = num / 100 ;
728
+ num2 = num % 100 ;
729
+ }
730
+ if ((n == 4 || n == 2 ) && !nodate (tm ) &&
731
+ set_time (num1 , num2 , 0 , tm ) == 0 )
732
+ return n ;
733
+ /*
734
+ * We thought this is an ISO-8601 time string,
735
+ * we set minutes and seconds to 0,
736
+ * turn out it isn't, rollback the change.
737
+ */
738
+ tm -> tm_min = tm -> tm_sec = -1 ;
739
+ }
740
+
704
741
/* Four-digit year or a timezone? */
705
742
if (n == 4 ) {
706
743
if (num <= 1400 && * offset == -1 ) {
0 commit comments