Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to enforce strict parsing in Boost::DateTime

Tags:

c++

boost

In the application I'm working on, I receive as an input a datetime in ISO format ( %Y-%m-%dT%H:%M:%SZ ).

I'd like to check that the received string is indeed in the specified format. I wanted to try the Boost DateTime library, which seemed perfect for this task.

However, I am surprised by the behavior of the DateTime parsing. My code is the following:

#include <string>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <sstream>

int main()
{
  std::string inputDate = "2017-01-31T02:15:53Z";
  std::string expectedFormat = "%Y-%m-%dT%H:%M:%SZ";

  boost::posix_time::time_input_facet *timeFacet = new boost::posix_time::time_input_facet(expectedFormat);

  std::stringstream datetimeStream(inputDate);
  datetimeStream.imbue(std::locale(std::locale::classic(), timeFacet));

  boost::posix_time::ptime outputTime;
  datetimeStream >> outputTime;
  if (datetimeStream.fail())
  {
    std::cout << "Failure" << std::endl;
  }
  std::cout << outputTime << std::endl;
  return 0;
}

When running this program, the output is:

2017-Jan-31 02:15:53

As expected. However if I change the inputDate to an invalid datetime like "2017-01-31T02:15:63Z" (63 seconds should not be accepted), the output will be

2017-Jan-31 02:16:03

Instead of a "Failure" message. I understand the logic behind, but I'd like to enforce a more strict parsing. Moreover, the parsing will still work when using "2017-01-31T02:15:53Z I like Stackoverflow" as the input, which is even stranger considering it doesn't respect the specified format.

So my question is: How to force Boost DateTime to reject strings that are not strictly respecting the format defined in the time_input_facet ?

Thanks

like image 230
Shuny Avatar asked Nov 17 '25 06:11

Shuny


1 Answers

Can you use another free, open-source, header-only date/time library?

#include "date/date.h"
#include <iostream>
#include <sstream>

int
main()
{
    std::string inputDate = "2017-01-31T02:15:63Z";
    std::string expectedFormat = "%Y-%m-%dT%H:%M:%SZ";
    std::stringstream datetimeStream{inputDate};
    date::sys_seconds outputTime;
    datetimeStream >> date::parse(expectedFormat, outputTime);
    if (datetimeStream.fail())
    {
        std::cout << "Failure" << std::endl;
    }
    using date::operator<<;
    std::cout << outputTime << std::endl;
}

Output:

Failure
1970-01-01 00:00:00
like image 146
Howard Hinnant Avatar answered Nov 18 '25 19:11

Howard Hinnant