Skip to content

Commit d2917b9

Browse files
committed
Merge branch 'ph/parse-date-reduced-precision'
Loosen date parsing heuristics. * ph/parse-date-reduced-precision: date.c: allow ISO 8601 reduced precision times
2 parents e28d5d2 + b56be49 commit d2917b9

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed

date.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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) {

t/t0006-date.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ check_parse 2008-02-14 bad
8888
check_parse '2008-02-14 20:30:45' '2008-02-14 20:30:45 +0000'
8989
check_parse '2008-02-14 20:30:45 -0500' '2008-02-14 20:30:45 -0500'
9090
check_parse '2008.02.14 20:30:45 -0500' '2008-02-14 20:30:45 -0500'
91+
check_parse '20080214T20:30:45' '2008-02-14 20:30:45 +0000'
92+
check_parse '20080214T20:30' '2008-02-14 20:30:00 +0000'
93+
check_parse '20080214T20' '2008-02-14 20:00:00 +0000'
94+
check_parse '20080214T203045' '2008-02-14 20:30:45 +0000'
95+
check_parse '20080214T2030' '2008-02-14 20:30:00 +0000'
96+
check_parse '20080214T000000.20' '2008-02-14 00:00:00 +0000'
97+
check_parse '20080214T00:00:00.20' '2008-02-14 00:00:00 +0000'
9198
check_parse '20080214T203045-04:00' '2008-02-14 20:30:45 -0400'
9299
check_parse '20080214T203045 -04:00' '2008-02-14 20:30:45 -0400'
93100
check_parse '20080214T203045.019-04:00' '2008-02-14 20:30:45 -0400'
@@ -99,6 +106,7 @@ check_parse '2008-02-14 20:30:45 -05' '2008-02-14 20:30:45 -0500'
99106
check_parse '2008-02-14 20:30:45 -:30' '2008-02-14 20:30:45 +0000'
100107
check_parse '2008-02-14 20:30:45 -05:00' '2008-02-14 20:30:45 -0500'
101108
check_parse '2008-02-14 20:30:45' '2008-02-14 20:30:45 -0500' EST5
109+
check_parse 'Thu, 7 Apr 2005 15:14:13 -0700' '2005-04-07 15:14:13 -0700'
102110

103111
check_approxidate() {
104112
echo "$1 -> $2 +0000" >expect

0 commit comments

Comments
 (0)