6

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

Pablo Yaggi
  • 1,061
  • 5
  • 14
  • Very interesting problem. I don't know if it's possible but you could try creating your own custom [locale](https://en.cppreference.com/w/cpp/locale/locale) and override the [get_time](https://en.cppreference.com/w/cpp/locale/time_get) 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. – paddy Dec 07 '21 at 03:21
  • 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. – Pablo Yaggi Dec 07 '21 at 03:57
  • 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 ;) – paddy Dec 07 '21 at 04:05

1 Answers1

-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;
daohu527
  • 452
  • 4
  • 15
  • 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. – Pablo Yaggi Dec 07 '21 at 04:02
  • 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. – daohu527 Dec 07 '21 at 05:50