diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/time/ISO8601.cxx | 63 |
1 files changed, 49 insertions, 14 deletions
diff --git a/src/time/ISO8601.cxx b/src/time/ISO8601.cxx index 42bba021f..32527d053 100644 --- a/src/time/ISO8601.cxx +++ b/src/time/ISO8601.cxx @@ -112,23 +112,58 @@ static const char * ParseTimeOfDay(const char *s, struct tm &tm, std::chrono::system_clock::duration &precision) noexcept { - const char *end; + /* this function always checks "end==s" to work around a + strptime() bug on OS X: if nothing could be parsed, + strptime() returns the input string (indicating success) + instead of nullptr (indicating error) */ - 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) + const char *end = strptime(s, "%H", &tm); + if (end == nullptr || end == s) + return end; + + s = end; + precision = std::chrono::hours(1); + + if (*s == ':') { + /* with field separators: now a minute must follow */ + + ++s; + + end = strptime(s, "%M", &tm); + if (end == nullptr || end == s) + return nullptr; + + s = end; precision = std::chrono::minutes(1); - else if ((end = strptime(s, "%H", &tm)) != nullptr) - precision = std::chrono::hours(1); - else - return nullptr; + /* the "seconds" field is optional */ + if (*s != ':') + return s; + + ++s; + + end = strptime(s, "%S", &tm); + if (end == nullptr || end == s) + return nullptr; + + precision = std::chrono::seconds(1); + return end; + } + + /* without field separators */ + + end = strptime(s, "%M", &tm); + if (end == nullptr || end == s) + return s; + + s = end; + precision = std::chrono::minutes(1); + + end = strptime(s, "%S", &tm); + if (end == nullptr || end == s) + return s; + + precision = std::chrono::seconds(1); return end; } |