@@ -493,6 +493,12 @@ static int match_alpha(const char *date, struct tm *tm, int *offset)
493493 return 2 ;
494494 }
495495
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+
496502 /* BAD CRAP */
497503 return skip_alpha (date );
498504}
@@ -638,6 +644,18 @@ static inline int nodate(struct tm *tm)
638644 tm -> tm_sec ) < 0 ;
639645}
640646
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+
641659/*
642660 * We've seen a digit. Time? Year? Date?
643661 */
@@ -701,6 +719,25 @@ static int match_digit(const char *date, struct tm *tm, int *offset, int *tm_gmt
701719 return end - date ;
702720 }
703721
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+
704741 /* Four-digit year or a timezone? */
705742 if (n == 4 ) {
706743 if (num <= 1400 && * offset == -1 ) {
0 commit comments