This is a question about invalid input, not invalid formatting. For example given the following code:
tm bar;
foo >> get_time(&bar, "%Y-%m-%d");
cout >> bar.tm_year >> bar.tm_mon >> bar.tm_mday >> endl;
This is fine if I define: stringstream foo("2001-02-28 non-leap year");
And has a clear error if I have invalid format such as: stringstream foo("bad format 2001-02-28 non-leap year");
But I don't know how to detect if my input was invalid for example:
stringstream foo("2001-02-30 non-leap year");
In this case bar
can be read as though nothing was wrong. Is there something I can listen for which will alert me that the input was invalid?
As is mentioned by Matteo Italia's answer, apart from writing your own Gregorian validator, your only reliable double check is mktime
. tm
s obtained with get_time
cannot be validated, as fields may and may not be filled out. Consider the following 2 invalid examples:
Doing this: istringstream("2001-02-30") >> get_time(&bar, "%Y-%m-%d");
results in a result that would change when run thorough mktime
:
bar.tm_mday
: 30
bar.tm_mon
: 1
bar.tm_year
: 100
While doing this: istringstream("2001-13-30") >> get_time(&bar, "%Y-%m-%d");
results in a result that would not change when run through mktime
:
bar.tm_mday
: 13
bar.tm_mon
: 0
bar.tm_year
: 100
In order to have all invalid dates altered by mktime
we need to read the date in without the use of get_time
:
int year;
int month;
int day;
istringstream foo("2000-13-30");
foo >> year >> ws;
foo.ignore();
foo >> month >> ws;
foo.ignore();
foo >> day;
tm bar = { 0, 0, 0, day, month - 1, year - 1900 };
At this point any error in bar
may be corrected by mktime
so our actual validation step will be to check for a non-time_t(-1)
return and compare the modified bar
back to the original values:
if(time_t(-1) != mktime(&bar) && bar.tm_mday == day && bar.tm_mon == month - 1 && bar.tm_year == year - 1900)
if this condition is true then the input to bar
was valid.
In conclusion, it is possible to validate a tm
without writing a Gregorian validator, but it is not possible to validate a tm
that has been read in by get_time
.