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

classic Classic list List threaded Threaded
17 messages Options
Reply | Threaded
Open this post in threaded view
|

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

Andrew Holden


> -----Original Message-----
> From: Christian Henning [mailto:[hidden email]]
> Sent: Tuesday, March 21, 2006 4:23 PM
> To: [hidden email]
> 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
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [date_time] How to create a date from stringwithspecific format?

Alexandre Gacon
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 : [hidden email]
[mailto:[hidden email]] De la part de Andrew Holden
Envoyé : mardi 21 mars 2006 23:18
À : [hidden email]
Objet : Re: [Boost-users] [date_time] How to create a date from
stringwithspecific format?



> -----Original Message-----
> From: Christian Henning [mailto:[hidden email]]
> Sent: Tuesday, March 21, 2006 4:23 PM
> To: [hidden email]
> 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
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users

_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [date_time] How to create a date from stringwithspecific format?

Christian Henning
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
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

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

Christian Henning
In reply to this post by Andrew Holden
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
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [date_time] How to create a date fromstringwithspecific format?

Alexandre Gacon
In reply to this post by Christian Henning
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 : [hidden email]
[mailto:[hidden email]] De la part de Christian Henning
Envoyé : mercredi 22 mars 2006 15:01
À : [hidden email]
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
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users

_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [date_time] How to create a date from stringwithspecific format?

Andrew Holden
In reply to this post by Alexandre Gacon


> -----Original Message-----
> From: Christian Henning [mailto:[hidden email]]
> Sent: Wednesday, March 22, 2006 9:22 AM
> To: [hidden email]
> Subject: Re: [Boost-users] [date_time] How to create a date from
> stringwithspecific format?
>
> 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

The code seems to work correctly on my machine (MSVC8 with Boost
1.33.1).  It throws an out of range error because strDate specifies
November 33.  If I change strDate to 11-30-1997, then I can "cout << d"
and get the date.

_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [date_time] How to create a date fromstringwithspecific format?

Christian Henning
In reply to this post by Alexandre Gacon
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
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [date_time] How to create a date from stringwithspecific format?

Christian Henning
In reply to this post by Andrew Holden
Andrew, the following code is not working on my machine. Can you check
if it is on your machine, please? The size of the match container is
just one. I'm using VC7.1 and Boost 1.33.1.

int _tmain(int argc, _TCHAR* argv[])
{
   //second approach
   boost::regex oDateReg2( "\\d{2}-\\d{2}-\\d{4}" );
   std::string strDate2( "11-22-1997" );

   boost::smatch dateMatch;

   if( boost::regex_match( strDate2
                         , dateMatch
                         , oDateReg2 ))
   {
      try
      {
         size_t nMatchSize = dateMatch.size();

         if( nMatchSize >= 4 )
         {
            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();
         }
         else
         {
            std::cerr << "Error. ";
         }
      }
      catch( std::out_of_range oEx )
      {
         std::cout << "Error: " << oEx.what() << std::endl;
      }
      catch( std::exception oEx )
      {
         std::cout << "Error: " << oEx.what() << std::endl;
      }
   }


        return 0;
}

When I run the captures_examples of the regex lib the smatch stuff
works. But not here. Very strange.

Thanks,
Christian
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [date_time] How to create a datefromstringwithspecific format?

Alexandre Gacon
In reply to this post by Christian Henning
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 : [hidden email]
[mailto:[hidden email]] De la part de Christian Henning
Envoyé : mercredi 22 mars 2006 16:30
À : [hidden email]
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
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users

_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [date_time] How to create a date fromstringwithspecific format?

Jeff Garland
In reply to this post by Christian Henning
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
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [date_time] How to create a datefromstringwithspecific format?

Christian Henning
In reply to this post by Alexandre Gacon
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
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [date_time] How to create adatefromstringwithspecific format?

Alexandre Gacon
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 : [hidden email]
[mailto:[hidden email]] De la part de Christian Henning
Envoyé : mercredi 22 mars 2006 16:56
À : [hidden email]
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
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users

_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [date_time] How to create a date fromstringwithspecific format?

Christian Henning
In reply to this post by Jeff Garland
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
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [date_time] How to create a date fromstringwithspecific format?

Andrew Holden
> -----Original Message-----
> From: Christian Henning
>
> int _tmain(int argc, _TCHAR* argv[])
> {
>    //second approach
>    boost::regex oDateReg2( "\\d{2}-\\d{2}-\\d{4}" );

The parentheses in my version of the example were important.  They
specify the size of the match object, as well as the exact portions of
the string to capture.  This line should read as follows:

boost::regex oDateReg2( "(\\d{2})-(\\d{2})-(\\d{4})" );

or if you wish to allow single-digit months and days,

boost::regex oDateReg2( "(\\d{1,2})-(\\d{1,2})-(\\d{4})" );

FYI, the order of the match object is the same as the CLOSING
parentheses.  This is good to know if you ever start nesting them.

>
> When I run the captures_examples of the regex lib the smatch stuff
> works. But not here. Very strange.
>
> Thanks,
> Christian
> _______________________________________________
> Boost-users mailing list
> [hidden email]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users

_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [date_time] How to create a date from stringwithspecific format?

Sebastian Redl
In reply to this post by Christian Henning
Christian Henning wrote:

>Andrew, the following code is not working on my machine. Can you check
>if it is on your machine, please? The size of the match container is
>just one. I'm using VC7.1 and Boost 1.33.1.
>
>int _tmain(int argc, _TCHAR* argv[])
>{
>   //second approach
>   boost::regex oDateReg2( "\\d{2}-\\d{2}-\\d{4}" );
>   std::string strDate2( "11-22-1997" );
>  
>
This regular expression does not contain captures. The size of the match
container is supposed to be 1. Try this instead:

boost::regex oDateReg2( "(\\d{2})-(\\d{2})-(\\d{4})" );


Sebastian Redl
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [date_time] How to create a date fromstringwithspecific format?

Jeff Garland
In reply to this post by Christian Henning
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
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [date_time] How to create a date fromstringwithspecific format?

Jeff Garland
In reply to this post by Christian Henning
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....
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users