mirror of
https://github.com/HowardHinnant/date.git
synced 2025-01-14 01:37:57 +08:00
Improve error message while parsing posix timezone string
This commit is contained in:
parent
abe3ada04f
commit
569b2d6785
@ -36,6 +36,9 @@
|
|||||||
// Posix::time_zone tz{"EST5EDT,M3.2.0,M11.1.0"};
|
// Posix::time_zone tz{"EST5EDT,M3.2.0,M11.1.0"};
|
||||||
// zoned_time<system_clock::duration, Posix::time_zone> zt{tz, system_clock::now()};
|
// zoned_time<system_clock::duration, Posix::time_zone> zt{tz, system_clock::now()};
|
||||||
//
|
//
|
||||||
|
// If the rule set is missing (everything starting with ','), then the rule is that the
|
||||||
|
// alternate offset is never enabled.
|
||||||
|
//
|
||||||
// Note, Posix-style time zones are not recommended for all of the reasons described here:
|
// Note, Posix-style time zones are not recommended for all of the reasons described here:
|
||||||
// https://stackoverflow.com/tags/timezone/info
|
// https://stackoverflow.com/tags/timezone/info
|
||||||
//
|
//
|
||||||
@ -70,7 +73,8 @@ unsigned read_date(const string_t& s, unsigned i, rule& r);
|
|||||||
unsigned read_name(const string_t& s, unsigned i, std::string& name);
|
unsigned read_name(const string_t& s, unsigned i, std::string& name);
|
||||||
unsigned read_signed_time(const string_t& s, unsigned i, std::chrono::seconds& t);
|
unsigned read_signed_time(const string_t& s, unsigned i, std::chrono::seconds& t);
|
||||||
unsigned read_unsigned_time(const string_t& s, unsigned i, std::chrono::seconds& t);
|
unsigned read_unsigned_time(const string_t& s, unsigned i, std::chrono::seconds& t);
|
||||||
unsigned read_unsigned(const string_t& s, unsigned i, unsigned limit, unsigned& u);
|
unsigned read_unsigned(const string_t& s, unsigned i, unsigned limit, unsigned& u,
|
||||||
|
const string_t& message = string_t{});
|
||||||
|
|
||||||
class rule
|
class rule
|
||||||
{
|
{
|
||||||
@ -584,7 +588,7 @@ throw_invalid(const string_t& s, unsigned i, const string_t& message)
|
|||||||
std::string(s) + '\n' +
|
std::string(s) + '\n' +
|
||||||
"\x1b[1;32m" +
|
"\x1b[1;32m" +
|
||||||
std::string(i, '~') + '^' +
|
std::string(i, '~') + '^' +
|
||||||
std::string(s.size()-i-1, '~') +
|
std::string(i < s.size() ? s.size()-i-1 : 0, '~') +
|
||||||
"\x1b[0m");
|
"\x1b[0m");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -600,7 +604,7 @@ read_date(const string_t& s, unsigned i, rule& r)
|
|||||||
{
|
{
|
||||||
++i;
|
++i;
|
||||||
unsigned n;
|
unsigned n;
|
||||||
i = read_unsigned(s, i, 3, n);
|
i = read_unsigned(s, i, 3, n, "Expected to find the Julian day [1, 365]");
|
||||||
r.mode_ = rule::J;
|
r.mode_ = rule::J;
|
||||||
r.n_ = n;
|
r.n_ = n;
|
||||||
}
|
}
|
||||||
@ -608,17 +612,17 @@ read_date(const string_t& s, unsigned i, rule& r)
|
|||||||
{
|
{
|
||||||
++i;
|
++i;
|
||||||
unsigned m;
|
unsigned m;
|
||||||
i = read_unsigned(s, i, 2, m);
|
i = read_unsigned(s, i, 2, m, "Expected to find month [1, 12]");
|
||||||
if (i == s.size() || s[i] != '.')
|
if (i == s.size() || s[i] != '.')
|
||||||
throw_invalid(s, i, "Expected '.' after month");
|
throw_invalid(s, i, "Expected '.' after month");
|
||||||
++i;
|
++i;
|
||||||
unsigned n;
|
unsigned n;
|
||||||
i = read_unsigned(s, i, 1, n);
|
i = read_unsigned(s, i, 1, n, "Expected to find week number [1, 5]");
|
||||||
if (i == s.size() || s[i] != '.')
|
if (i == s.size() || s[i] != '.')
|
||||||
throw_invalid(s, i, "Expected '.' after weekday index");
|
throw_invalid(s, i, "Expected '.' after weekday index");
|
||||||
++i;
|
++i;
|
||||||
unsigned wd;
|
unsigned wd;
|
||||||
i = read_unsigned(s, i, 1, wd);
|
i = read_unsigned(s, i, 1, wd, "Expected to find day of week [0, 6]");
|
||||||
r.mode_ = rule::M;
|
r.mode_ = rule::M;
|
||||||
r.m_ = month{m};
|
r.m_ = month{m};
|
||||||
r.wd_ = weekday{wd};
|
r.wd_ = weekday{wd};
|
||||||
@ -708,17 +712,17 @@ read_unsigned_time(const string_t& s, unsigned i, std::chrono::seconds& t)
|
|||||||
if (i == s.size())
|
if (i == s.size())
|
||||||
throw_invalid(s, i, "Expected to read unsigned time, but found end of string");
|
throw_invalid(s, i, "Expected to read unsigned time, but found end of string");
|
||||||
unsigned x;
|
unsigned x;
|
||||||
i = read_unsigned(s, i, 2, x);
|
i = read_unsigned(s, i, 2, x, "Expected to find hours [0, 24]");
|
||||||
t = hours{x};
|
t = hours{x};
|
||||||
if (i != s.size() && s[i] == ':')
|
if (i != s.size() && s[i] == ':')
|
||||||
{
|
{
|
||||||
++i;
|
++i;
|
||||||
i = read_unsigned(s, i, 2, x);
|
i = read_unsigned(s, i, 2, x, "Expected to find minutes [0, 59]");
|
||||||
t += minutes{x};
|
t += minutes{x};
|
||||||
if (i != s.size() && s[i] == ':')
|
if (i != s.size() && s[i] == ':')
|
||||||
{
|
{
|
||||||
++i;
|
++i;
|
||||||
i = read_unsigned(s, i, 2, x);
|
i = read_unsigned(s, i, 2, x, "Expected to find seconds [0, 59]");
|
||||||
t += seconds{x};
|
t += seconds{x};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -727,10 +731,11 @@ read_unsigned_time(const string_t& s, unsigned i, std::chrono::seconds& t)
|
|||||||
|
|
||||||
inline
|
inline
|
||||||
unsigned
|
unsigned
|
||||||
read_unsigned(const string_t& s, unsigned i, unsigned limit, unsigned& u)
|
read_unsigned(const string_t& s, unsigned i, unsigned limit, unsigned& u,
|
||||||
|
const string_t& message)
|
||||||
{
|
{
|
||||||
if (i == s.size() || !std::isdigit(s[i]))
|
if (i == s.size() || !std::isdigit(s[i]))
|
||||||
throw_invalid(s, i, "Expected to find a decimal digit");
|
throw_invalid(s, i, message);
|
||||||
u = static_cast<unsigned>(s[i] - '0');
|
u = static_cast<unsigned>(s[i] - '0');
|
||||||
unsigned count = 1;
|
unsigned count = 1;
|
||||||
for (++i; count < limit && i != s.size() && std::isdigit(s[i]); ++i, ++count)
|
for (++i; count < limit && i != s.size() && std::isdigit(s[i]); ++i, ++count)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user