diff --git a/NEWS b/NEWS index 986f22c87..1467ddb97 100644 --- a/NEWS +++ b/NEWS @@ -1,7 +1,7 @@ ver 0.21.17 (not yet released) * protocol - - relax the ISO 8601 parser: allow omitting the time of day and the "Z" - suffix + - relax the ISO 8601 parser: allow omitting field separators, the + time of day and the "Z" suffix * archive - zzip: improve error reporting * outputs diff --git a/src/time/ISO8601.cxx b/src/time/ISO8601.cxx index b92a0e743..5cb4c486c 100644 --- a/src/time/ISO8601.cxx +++ b/src/time/ISO8601.cxx @@ -123,8 +123,12 @@ ParseISO8601(const char *s) /* parse the date */ const char *end = strptime(s, "%F", &tm); - if (end == nullptr) - throw std::runtime_error("Failed to parse date"); + if (end == nullptr) { + /* try without field separators */ + end = strptime(s, "%Y%m%d", &tm); + if (end == nullptr) + throw std::runtime_error("Failed to parse date"); + } s = end; @@ -136,6 +140,12 @@ ParseISO8601(const char *s) if ((end = strptime(s, "%T", &tm)) != nullptr) precision = std::chrono::seconds(1); + else if ((end = strptime(s, "%H%M%S", &tm)) != nullptr) + /* no field separators */ + precision = std::chrono::seconds(1); + else if ((end = strptime(s, "%H%M", &tm)) != nullptr) + /* no field separators */ + precision = std::chrono::minutes(1); else if ((end = strptime(s, "%H:%M", &tm)) != nullptr) precision = std::chrono::minutes(1); else if ((end = strptime(s, "%H", &tm)) != nullptr) diff --git a/test/TestISO8601.cxx b/test/TestISO8601.cxx index 3305b47de..cd0897c1a 100644 --- a/test/TestISO8601.cxx +++ b/test/TestISO8601.cxx @@ -71,6 +71,15 @@ static constexpr struct { { "2019-02-04T16:46:41+0200", 1549291601, std::chrono::seconds(1) }, { "2019-02-04T16:46:41+02:00", 1549291601, std::chrono::seconds(1) }, { "2019-02-04T16:46:41-0200", 1549306001, std::chrono::seconds(1) }, + + /* without field separators */ + { "19700101T000000Z", 0, std::chrono::seconds(1) }, + { "19700101T000001Z", 1, std::chrono::seconds(1) }, + { "20190204T164641Z", 1549298801, std::chrono::seconds(1) }, + { "19700101", 0, std::chrono::hours(24) }, + { "20190204", 1549238400, std::chrono::hours(24) }, + { "20190204T1646", 1549298760, std::chrono::minutes(1) }, + { "20190204T16", 1549296000, std::chrono::hours(1) }, }; TEST(ISO8601, Parse)