Re: [Boost-users] [date_time] How to create a date from string withspecific format?

-----Original Message----- From: Christian Henning [mailto:chhenning@gmail.com] Sent: Tuesday, March 21, 2006 4:23 PM To: boost-users@lists.boost.org Subject: Re: [Boost-users] [date_time] How to create a date from string withspecific format?
Hi Dean, thanks for the answer.
Since, I know the format of the date strings I could also use boost::regex for the general format and then feeding a date object with the values. If I get an exception during the date object contruction I know that the user provided me with garbage.
Any thoughts on that?
Thanks again, Christian
Have you considered using Regex's submatches? A slightly modified example follows. // date format: mm-dd-yyyy boost::regex oDateReg( "(\\d{2})-(\\d{2})-(\\d{4})" ); std::string strDate( "11-33-1997" ); boost::smatch dateMatch; if( boost::regex_match( strDate , dateMatch , oDateReg )) { try { std::string strMonth = dateMatch[1]; std::string strDay = dateMatch[2]; std::string strYear = dateMatch[3]; unsigned int nYear = boost::lexical_cast<unsigned int>(strYear); unsigned int nMonth = boost::lexical_cast<unsigned int>(strMonth); unsigned int nDay = boost::lexical_cast<unsigned int>(strDay); date d( nYear, nMonth, nDay ); date::ymd_type ymd = d.year_month_day(); } catch( std::out_of_range oEx ) { std::cout << "Error: " << oEx.what() << std::endl; } } There are two advantages to this. First, you no longer need to count characters when extracting the date components. Second, you have a little more freedom in defining your date format. For example, you could use the following definition for oDateReg to also accept single-digit months and/or days: boost::regex oDateReg( "(\\d{1,2})-(\\d{1,2})-(\\d{4})" ); Andrew Holden

Why don't you use the input/output facet with a stream to define the format you want ? For example I was able to define my own time format as simply as this: pt::time_input_facet* pInputFacet = new pt::time_input_facet(); pInputFacet->time_duration_format( "%H:%M" ); std::locale loc( std::locale::classic(), pInputFacet ); ss.imbue( loc ); You can do the same with the boost::gregorian::date. Check the documentation (at least if you use the 1.33.1 version of boost). I hope it will help you. Alexandre Gacon -----Message d'origine----- De : boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] De la part de Andrew Holden Envoyé : mardi 21 mars 2006 23:18 À : boost-users@lists.boost.org Objet : Re: [Boost-users] [date_time] How to create a date from stringwithspecific format?
-----Original Message----- From: Christian Henning [mailto:chhenning@gmail.com] Sent: Tuesday, March 21, 2006 4:23 PM To: boost-users@lists.boost.org Subject: Re: [Boost-users] [date_time] How to create a date from string withspecific format?
Hi Dean, thanks for the answer.
Since, I know the format of the date strings I could also use boost::regex for the general format and then feeding a date object with the values. If I get an exception during the date object contruction I know that the user provided me with garbage.
Any thoughts on that?
Thanks again, Christian
Have you considered using Regex's submatches? A slightly modified example follows. // date format: mm-dd-yyyy boost::regex oDateReg( "(\\d{2})-(\\d{2})-(\\d{4})" ); std::string strDate( "11-33-1997" ); boost::smatch dateMatch; if( boost::regex_match( strDate , dateMatch , oDateReg )) { try { std::string strMonth = dateMatch[1]; std::string strDay = dateMatch[2]; std::string strYear = dateMatch[3]; unsigned int nYear = boost::lexical_cast<unsigned int>(strYear); unsigned int nMonth = boost::lexical_cast<unsigned int>(strMonth); unsigned int nDay = boost::lexical_cast<unsigned int>(strDay); date d( nYear, nMonth, nDay ); date::ymd_type ymd = d.year_month_day(); } catch( std::out_of_range oEx ) { std::cout << "Error: " << oEx.what() << std::endl; } } There are two advantages to this. First, you no longer need to count characters when extracting the date components. Second, you have a little more freedom in defining your date format. For example, you could use the following definition for oDateReg to also accept single-digit months and/or days: boost::regex oDateReg( "(\\d{1,2})-(\\d{1,2})-(\\d{4})" ); Andrew Holden _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Alexandre, this was my initial approach of the problem, but somehow I couldn't figure out how to construct the data or time object? ptime oTime ss >> oTime; //??????? Thanks, Christian

boost::date_time::date_input_facet* pMyFacet = new boost::date_time::date_input_facet( "%m-%d-%Y" ); std::locale loc( std::locale::classic(), pMyFacet ); std::istringstream ss; ss.str( "22-03-2006" ); Boost::gregorian::date myDate; ss >> myDate; Normally, myDate must be initialized to the 22-03-2006 like indicated. Alexandre -----Message d'origine----- De : boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] De la part de Christian Henning Envoyé : mercredi 22 mars 2006 15:01 À : boost-users@lists.boost.org Objet : Re: [Boost-users] [date_time] How to create a date fromstringwithspecific format? Alexandre, this was my initial approach of the problem, but somehow I couldn't figure out how to construct the data or time object? ptime oTime ss >> oTime; //??????? Thanks, Christian _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Alexandre, the following code will give an exception stating "Error: Year is out of valid range: 1400..10000". I don't think the myDate object is correctly initialized. Can you check this on your machine, please. Can you call myDate.year_month_day()? date_input_facet* pMyFacet = new date_input_facet( "%m-%d-%Y" ); std::locale loc( std::locale::classic(), pMyFacet ); std::istringstream oo; oo.str( "22-03-2006" ); date myDate; try { oo >> myDate; date::ymd_type ymd = myDate.year_month_day(); } catch( std::out_of_range oEx ) { std::cout << "Error: " << oEx.what() << std::endl; } Thanks ahead, Christian

What format do you want for your date ? In your first mail, you mention "MM-DD-YYYY" for the format but in your sample you use a "DD-MM-YYYY" format ! If you want the "DD-MM-YYYY" format, you can simply use the function boost::gregorian::from_uk_string(std::string s). Alexandre -----Message d'origine----- De : boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] De la part de Christian Henning Envoyé : mercredi 22 mars 2006 16:30 À : boost-users@lists.boost.org Objet : Re: [Boost-users] [date_time] How to create a datefromstringwithspecific format? Alexandre, the following code will give an exception stating "Error: Year is out of valid range: 1400..10000". I don't think the myDate object is correctly initialized. Can you check this on your machine, please. Can you call myDate.year_month_day()? date_input_facet* pMyFacet = new date_input_facet( "%m-%d-%Y" ); std::locale loc( std::locale::classic(), pMyFacet ); std::istringstream oo; oo.str( "22-03-2006" ); date myDate; try { oo >> myDate; date::ymd_type ymd = myDate.year_month_day(); } catch( std::out_of_range oEx ) { std::cout << "Error: " << oEx.what() << std::endl; } Thanks ahead, Christian _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

I would like to leave that open for the user. My application will support locals soon and the format of date strings will depend on the local settings. So, I'm looking for a general solution for my problem. Was the code I sent in my last email working on your machine? Thanks for your input, Christian

Like indicated by Jeff, I forgot to add the imbue call So you can add to your code: date_input_facet* pMyFacet = new date_input_facet( "%m-%d-%Y" ); std::locale loc( std::locale::classic(), pMyFacet ); std::istringstream oo; oo.imbue( loc ); // $$$$$ code added oo.str( "22-03-2006" ); date myDate; try { oo >> myDate; date::ymd_type ymd = myDate.year_month_day(); } catch( std::out_of_range oEx ) { std::cout << "Error: " << oEx.what() << std::endl; } If you want to give more control to the user, check the boost documentation for the different formats. Alexandre -----Message d'origine----- De : boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] De la part de Christian Henning Envoyé : mercredi 22 mars 2006 16:56 À : boost-users@lists.boost.org Objet : Re: [Boost-users] [date_time] How to create adatefromstringwithspecific format? I would like to leave that open for the user. My application will support locals soon and the format of date strings will depend on the local settings. So, I'm looking for a general solution for my problem. Was the code I sent in my last email working on your machine? Thanks for your input, Christian _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Christian Henning wrote:
Alexandre, the following code will give an exception stating "Error: Year is out of valid range: 1400..10000". I don't think the myDate object is correctly initialized. Can you check this on your machine, please. Can you call myDate.year_month_day()?
date_input_facet* pMyFacet = new date_input_facet( "%m-%d-%Y" );
std::locale loc( std::locale::classic(), pMyFacet );
std::istringstream oo; oo.str( "22-03-2006" );
date myDate; ...snip...
I'd say the format in the facet and the data don't match -- there is no month 22. If you want the string 22-03-2006 to work try date_input_facet( "%d-%m-%Y" ) Also, you will need to imbue the facet into the stringstream: oo.imbue(locale(oo.getloc(), date_input_facet)) This is why you are getting the year out of range exception -- because the default format for dates expects the year first and 22 is out of range. Jeff

Thank you very much. I was not paying to attention. My fault. For the records, here is a sample that works: date_input_facet* pMyFacet = new date_input_facet( "%m-%d-%Y" ); std::istringstream oo; oo.imbue( std::locale(oo.getloc(), pMyFacet )); oo.str( "11-03-2006" ); date myDate; try { oo >> myDate; date::ymd_type ymd = myDate.year_month_day(); std::cout << myDate; } catch( std::out_of_range oEx ) { std::cout << "Error: " << oEx.what() << std::endl; } Unfortunately a string like "11-3-1997" wont work since the day is just a single digit. Is that something the date_time lib will be able to understand in the future? Thanks, Christian

Christian Henning wrote:
Thank you very much. I was not paying to attention. My fault.
For the records, here is a sample that works:
date_input_facet* pMyFacet = new date_input_facet( "%m-%d-%Y" );
std::istringstream oo; oo.imbue( std::locale(oo.getloc(), pMyFacet )); oo.str( "11-03-2006" );
date myDate;
try { oo >> myDate;
date::ymd_type ymd = myDate.year_month_day();
std::cout << myDate; } catch( std::out_of_range oEx ) { std::cout << "Error: " << oEx.what() << std::endl; }
Unfortunately a string like "11-3-1997" wont work since the day is just a single digit. Is that something the date_time lib will be able to understand in the future?
Sure. I've uploaded an experimental change that you can try out to the vault: http://www.boost-consulting.com/vault/index.php?&direction=0&order=&directory=date_time Basically you need to drop the format_date_parser.hpp into you boost/date_time directory. This also allows for single digit days in addition to months. The only reason it's experimental is that it changes the behavior of failures for undelimited string parsing. For example, the iso format 2006021 will now succeed instead of failing. I believe this can be resolved, but it's going to take a bit more time... Jeff

Christian Henning wrote:
Thank you very much. I was not paying to attention. My fault.
For the records, here is a sample that works:
...snip details...
Unfortunately a string like "11-3-1997" wont work since the day is just a single digit. Is that something the date_time lib will be able to understand in the future?
Sure. I've uploaded an experimental change that you can try out to the vault: http://www.boost-consulting.com/vault/index.php?&direction=0&order=&directory=date_time Basically you need to drop the format_date_parser.hpp into you boost/date_time directory. This also allows for single digit days in addition to months. The only reason it's experimental is that it changes the behavior of failures for undelimited string parsing. For example, the iso format 2006021 will now succeed instead of failing. I believe this can be resolved, but it's going to take a bit more time... Jeff ps: I tried to post this yesterday, but it didn't work....

Andrew, thanks for pointing out the submatch feature. Unfortunately no match can be found when I try your code. Is it working on your machine? Here, the dateMatch container size just 1. Any ideas why? Christian
participants (4)
-
Alexandre Gacon
-
Andrew Holden
-
Christian Henning
-
Jeff Garland