https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124513
Bug ID: 124513
Summary: Parsing bug for TIME component of UNTIL field in Zone
lines
Product: gcc
Version: 16.0
Status: UNCONFIRMED
Keywords: wrong-code
Severity: normal
Priority: P3
Component: libstdc++
Assignee: unassigned at gcc dot gnu.org
Reporter: redi at gcc dot gnu.org
Target Milestone: ---
Zone lines which end in wall time specified as just a single digit number of
hours are not parsed correctly, e.g.
Z Antarctica/Mawson 0 - -00 1954 F 13
6 - %z 2009 O 18 2
5 - %z
The second line ending in "2" is not parsed correctly, because of a bug in
istream& operator>>(istream& in, at_time& at)
which looks like this:
int i;
in >> i;
hours h{i};
minutes m{};
seconds s{};
if (!in.eof() && in.peek() == ':')
{
[... parse optional minutes and seconds ...]
}
if (in >> at.indicator)
at.time = sign * (h + m + s);
return in;
If the line ends in just a digit then `in >> i` sets eofbit and then when
`in >> at.indicator` tries to peek at the next character, it sets failbit, and
so `in` is false, and we never execute the line that sets at.time.
This means we parse a time of 0 instead of 2.
Most zones are not affected, because they specify the time that the clocks
change in standard time, e.g. "2s".
Testcase:
#include <chrono>
#include <print>
int main()
{
using namespace std::chrono;
auto zone = locate_zone("Antarctica/Mawson");
auto info = zone->get_info(sys_days(2009y/October/19));
auto d = info.begin.time_since_epoch();
std::println("{}: {}", zone->name(), info.begin);
}
This prints:
Antarctica/Mawson: 2009-10-18 00:00:00
But the correct output would be:
Antarctica/Mawson: 2009-10-17 20:00:00
Because the clocks should change at 2am local time, which is 6h ahead of UTC,
so that's 8pm on the rpevious day in UTC.