summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/time/ISO8601.cxx63
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;
}