get_time parsing error for two digits year
Asked Answered
A

1

7

std::get_time is behaving in the same way when the format includes '%y' or '%Y', in both cases it tries to read a four digit year. Am I doing something wrong or is it a bug ?

Example code:

#include <iostream>
#include <iomanip>

void testDate(const char *format,const char *date)
{
    std::istringstream ds(date);

    std::tm tm = {};
    ds >> std::get_time(&tm,format);
    std::cout<<date<<" parsed using "<<format<<" -> Year: "<<tm.tm_year+1900<<" Month: "<<tm.tm_mon<<" Day: "<<tm.tm_mday<<std::endl;
}

int main()
{
    testDate("%y%m%d","101112");
    testDate("%Y%m%d","101112");
    testDate("%y%m%d","20101112");
    testDate("%Y%m%d","20101112");
    
    
    return 0;
}

Output:

101112 parsed using %y%m%d -> Year: 1011 Month: 11 Day: 0
101112 parsed using %Y%m%d -> Year: 1011 Month: 11 Day: 0
20101112 parsed using %y%m%d -> Year: 2010 Month: 10 Day: 12
20101112 parsed using %Y%m%d -> Year: 2010 Month: 10 Day: 12

Tested with:

g++ (SUSE Linux) 11.2.1 20210816 [revision 056e324ce46a7924b5cf10f61010cf9dd2ca10e9]

clang++ version 12.0.1

Aleksandr answered 7/12, 2021 at 2:50 Comment(3)
Very interesting problem. I don't know if it's possible but you could try creating your own custom locale and override the get_time facet and imbue that on the stream to examine whether get is being invoked, or if instead get_year is called, which would have no knowledge of look-ahead. If it is, then it certainly appears to deviate from the specification. If you're relying on this, you may be better off using your own string parsing or even regular expressions.Schechter
I was actually relying on this, but I have a work around. I will need it in the future, so finding out what is going on would be great. I think it is bug, but I wan't to check with everybody. I tried to look in the source code, but I'm having a hard time to find the 'actual' implementation in the gcc tree.Aleksandr
Yeah, I can imagine this is a dive down quite a rabbit hole. If it were me, I'd be rolling my own workaround and not relying on this at all. If not a bug, it's definitely a quirk. By adding any non-numeric character to the format following the year it works of course. It really looks like year is being parsed with a greedy algorithm which suggests to me that the standard library might be calling get_year as a fallback. Maybe there's a // TODO comment somewhere in that code ;)Schechter
H
-1

Found after testing

  • %y - Enter only two digits
  • %Y - Enter only four digits

If you use 4 digits when using %y, then 4 digits will be output directly, if it is 2 digits, it is consistent with the document

The Month

The Month, From the std::tm

tm_mon : months since January – [0, 11]

so it print out 11 represents December. You can use below code to print out the date.

    std::cout << std::put_time(&tm, "%c") << std::endl;
Hadfield answered 7/12, 2021 at 3:38 Comment(2)
You are miss reading the problem and the test scenario. The last output is correct, (the only one that doesn't seem to diverse from the documentation). Month should be 10, as in every input the month is November.Aleksandr
I found that gcc reports an error when running the above code, and it can run with clang. the gcc source code seems no problem.Hadfield

© 2022 - 2024 — McMap. All rights reserved.