Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Consistently parse various date and time formats with Howard Hinnant's date library

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:

  • YYYY
  • YYYY-mm
  • YYYY-mm-dd

The times are in the formats:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

  • HH:MM:SS
  • HH:MM:SS.ffffff

If a date and time are both defined, then a timezone must also be defined, like so:

  • YYYY-mm-ddTHH:MM:SS.ffffff+ZZ:ZZ
    • For example: 2012-03-04T05:06:07.123456+07:00

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?

>Solution :

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
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading