I need to be able to parse and store various dates, times, or both according to a subset of the ISO-8601 standard.
The dates are in the formats:
The times are in the formats:
If a date and time are both defined, then a timezone must also be defined, like so:
I tried to use Howard Hinnant's date library, the same one in the C++20 standard. It seems I need to use specific types to parse different formats which is slightly annoying. I would rather be able to parse and store any format within the same type.
To illustrate the problem:
sys_time<microseconds> sys_us;
microseconds us;
year_month ym;
year y;
std::istringstream iss;
iss.str("2012-03-04T05:06:07.123456+07:00");
iss >> date::parse("%FT%T%Ez", sys_us); // Only works with this type. (The others can't parse this much info.)
assert(!iss.fail());
iss.str("2012-03-04");
iss >> date::parse("%F", sys_us); // If the date has the full year, month, and day, this works.
assert(!iss.fail());
iss.str("2012-03");
// iss >> date::parse("%Y-%m", sys_us); // This fails; day is missing.
iss >> date::parse("%Y-%m", ym); // Works.
assert(!iss.fail());
iss.str("2012");
// iss >> date::parse("%Y", sys_us); // This fails.
// iss >> date::parse("%Y", ym); // Also fails; month is missing.
iss >> date::parse("%Y", y); // Works.
assert(!iss.fail());
iss.str("05:06:07.123456");
// iss >> date::parse("%T", sys_us); // Also fails; unhappy with missing date.
iss >> date::parse("%T", us); // Must use duration type for time instead.
assert(!iss.fail());
It would be much nicer if I could date::parse(format, obj)
where obj
didn't need to change types. Is that possible?
The only way to store them all in the same type is to pick the one with the most information (sys_time<microseconds>
), then do the parse in the partial types as you've shown and add defaults for those values not parsed.
For example:
iss.str("05:06:07.123456");
iss >> date::parse("%T", us); // Must use duration type for time
sys_us = sys_days{year{0}/1/1} + us; // Add defaulted date