Merge tag 'v0.21.18'

release v0.21.18
This commit is contained in:
Max Kellermann
2019-12-24 16:17:10 +01:00
20 changed files with 375 additions and 77 deletions

View File

@@ -58,6 +58,8 @@ FormatISO8601(std::chrono::system_clock::time_point tp)
return FormatISO8601(GmTime(tp));
}
#ifndef _WIN32
static std::pair<unsigned, unsigned>
ParseTimeZoneOffsetRaw(const char *&s)
{
@@ -108,6 +110,67 @@ ParseTimeZoneOffset(const char *&s)
return d;
}
static const char *
ParseTimeOfDay(const char *s, struct tm &tm,
std::chrono::system_clock::duration &precision) noexcept
{
/* 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) */
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);
/* 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;
}
#endif
std::pair<std::chrono::system_clock::time_point,
std::chrono::system_clock::duration>
ParseISO8601(const char *s)
@@ -138,22 +201,9 @@ ParseISO8601(const char *s)
if (*s == 'T') {
++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)
precision = std::chrono::hours(1);
else
s = ParseTimeOfDay(s, tm, precision);
if (s == nullptr)
throw std::runtime_error("Failed to parse time of day");
s = end;
}
auto tp = TimeGm(tm);