How to convert std :: string to boost :: gregorian :: date?

I am trying to convert std::string to boost::gregorian::date as follows:

 using namespace boost::gregorian; std::string str = "1 Mar 2012"; std::stringstream ss(str); date_input_facet *df = new date_input_facet("%e %b %Y"); ss.imbue(std::locale(ss.getloc(), df)); date d; ss >> d; //conversion fails to not-a-date-time std::cout << "'" << d << "'" << std::endl; //'not-a-date-time' 

But if the line contains "March 01, 2012," the conversion is successful.

How to convert strings like "March 1, 2012" to the equivalent of boost::gregorian::date ?

+8
c ++ boost boost-date-time
source share
1 answer

This would seem to be a problem with using %e in the input phase.

Boost.Gregorian documentation indicates that:

% d Day of the month as decimal 01 to 31

% e # Like% d, the day of the month as a decimal, but the leading zero is replaced by a space

The problem is that if you look at the top of the documentation, you will notice this warning:

Flags marked with a hash sign (#) are implemented according to the system language and, as you know, are absent on some platforms

I have tried the following cases:

 input_string = " 1" date_format = "%e" result = failed input_string = "01" date_format = "%e" result = success input_string = "2000 Mar 1" date_format = "%Y %b %e" result = failed input_string = "2000 Mar 1" date_format = "%Y %b %e" result = success input_string = "2000 Mar 01" date_format = "%Y %b %e" result = success 

This seems to be a limitation of the Boost implementation (or at least the fact that it depends on the specific locale for parsing %e ): parsing is not performed when %e is the first element in the input string and the space is used instead of leading 0 .

My (blind) assumption would be that the problem is due to the streamer’s tendency to skip spaces. I tried to find a solution with std::noskipws , however I could not find something that worked.

As a workaround, I would recommend adding a leading zero or, if possible, using a different date format.

Another workaround would be to manually add space and reverse the word order in the line. I implemented the following working solution:

 #include "boost/date_time/gregorian/gregorian.hpp" #include <iostream> #include <string> int main(void) { using namespace boost::gregorian; std::string input_date("1 Mar 2000"); { // local scope to remove temporary variables as soon as possible std::stringstream tmp_ss(input_date); std::string tmp; input_date.clear(); // empty the initial string while (tmp_ss >> tmp) { input_date.insert(0, tmp); // insert word at beginning of string if(tmp.size() == 1) // if word is one char long, add extra space input_date.insert(0, " "); input_date.insert(0, " "); // add space to separate words } } std::stringstream ss(input_date); // The order of the date is reversed. date_input_facet *df = new date_input_facet("%Y %b %e"); ss.imbue(std::locale(ss.getloc(), df)); date d; //conversion works ss >> d; std::cout << "'" << d << "'" << std::endl; // ouputs date correctly. return 0; } 

Good luck

+10
source share

All Articles