Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

What else shall I do before reusing a stringstream for date parsing?

122 views
Skip to first unread message

Bill David

unread,
Feb 16, 2009, 9:59:48 AM2/16/09
to
To accelerate date parsing, I have writen a class to encapsulate the
date parsing logic as following.
But the second call to CDateParser::parseDate(str) always failed to
parse the date string. What else shall I do before reuse the
stringstream object?

#include <stdio.h>

#include <iostream>
#include <sstream>
using namespace std;

#include "boost/date_time/posix_time/posix_time.hpp"
using namespace boost::gregorian;
using namespace boost::posix_time;

class CDateParser
{
public:
static void initialize();
static time_t parseDate(const string& s);
private:
static stringstream m_ss; //!< stringstream object used internally
for date parsing
};

stringstream CDateParser::m_ss;

time_t CDateParser::parseDate(const string& str)
{
ptime p;
m_ss.clear();
m_ss << str;
m_ss >> p;
if (m_ss.fail()) {
cout << "do not understand: " << str << endl;
return 0;
}

tm t = to_tm(p);
return mktime(&t);
}

void CDateParser::initialize() {
time_input_facet* timefacet = new time_input_facet("%a, %d %b %Y
%H:%M:%S %z"); // will be automatically deleted by related locale
object
m_ss.imbue(locale(locale::empty(), timefacet));
}

int main() {
CDateParser::initialize();

string str;
time_t t;

str = "Fri, 18 Jul 2008 11:53:14 GMT";
t = CDateParser::parseDate(str);
cout << ctime(&t) << endl;

str = "Sat, 19 Jul 2008 11:53:14 GMT";
t = CDateParser::parseDate(str);
cout << ctime(&t) << endl;
}

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

zero

unread,
Feb 16, 2009, 5:28:08 PM2/16/09
to
Bill David <billd...@gmail.com> wrote in news:7d65ac9c-ab23-4531-8cf9-
83f097...@p36g2000prp.googlegroups.com:

> To accelerate date parsing, I have writen a class to encapsulate the
> date parsing logic as following.
> But the second call to CDateParser::parseDate(str) always failed to
> parse the date string. What else shall I do before reuse the
> stringstream object?
>
> #include <stdio.h>
>
> #include <iostream>
> #include <sstream>
> using namespace std;

This statement effectively adds everything in the std namespace to the
global namespace, thus eliminating the whole reason behind namespaces.
Please don't do this. See
http://www.parashift.com/c++-faq-lite/coding-standards.html#faq-27.5

> #include "boost/date_time/posix_time/posix_time.hpp"
> using namespace boost::gregorian;
> using namespace boost::posix_time;

same remark as above

>
> class CDateParser
> {
> public:
> static void initialize();
> static time_t parseDate(const string& s);
> private:
> static stringstream m_ss; //!< stringstream object used internally
> for date parsing
> };

Why do you create a class with only static functions? Instead, try a
namespace. The private member can be emulated using an anonymous
namespace. Or, better yet, lose the initialize() function, put the
stringstream as a local variable in parseDate, and use a local static
boolean to initialize it the first time the function is called.

>
> stringstream CDateParser::m_ss;
>
> time_t CDateParser::parseDate(const string& str)
> {
> ptime p;
> m_ss.clear();

Here is the problem. From the context it looks like you expect this call
to reset the stringstream. It does not. stringstream::clear (actually
ios::clear) only clears the stream's state flags. This is most often used
to clear the bad_bit. However, it does not change the contents of the
stringstream.
To clear a stringstream, you should reset its str(), like so:
m_ss.str( "" );

> m_ss << str;
> m_ss >> p;
> if (m_ss.fail()) {
> cout << "do not understand: " << str << endl;
> return 0;
> }
>
> tm t = to_tm(p);
> return mktime(&t);
> }
>

<trim>

Eugene Zolenko

unread,
Feb 21, 2009, 10:48:06 AM2/21/09
to
zero wrote:
> Bill David <billd...@gmail.com> wrote in news:7d65ac9c-ab23-4531-8cf9-
> 83f097...@p36g2000prp.googlegroups.com:
>
>> To accelerate date parsing, I have writen a class to encapsulate the
>> date parsing logic as following.
>> But the second call to CDateParser::parseDate(str) always failed to
>> parse the date string. What else shall I do before reuse the
>> stringstream object?
>>
>> #include <stdio.h>
>>
>> #include <iostream>
>> #include <sstream>
>> using namespace std;
>
> This statement effectively adds everything in the std namespace to the
> global namespace, thus eliminating the whole reason behind namespaces.
> Please don't do this. See
> http://www.parashift.com/c++-faq-lite/coding-standards.html#faq-27.5

I find cpp files as end points of compilation are usually isolated
enough to allow for such liberties. It is very rare that potential
ambiguities are subtle enough to actually pass compilation and wreak
havoc in real time. (And when that happens they are so much more fun to
track down and nail to the trophy wall :))

Once found (mostly at the time of adding the conflicting code anyway)
they are easily managed by more explicitly specifying offending parts.
The control remains within cpp file, and those, unlike headers, should
be easy to change without affecting the rest of the code.

Huge monolithic source files that contain everything and their unit
tests are bad on their own merits and should be broken down instead.
Small and well contained files often don't mix too many namespaces
anyway. (Unless there are lots and lots of them in the project.)

Namespaces also affect linking, regardless of "using" directives, so not
the whole reason is eliminated. That, and the ability to control
visibility when needed without leaving boundaries of cpp file is what
makes them useful.

Having said that, I had my share of headdesks trying to compile code
like this:
cout << "bla" << end;
This is in one category with missing semicolons after class definitions
though, and most of the blame goes to compilers for shock value of sheer
volume and irrelevantness of their error messages.

"Using namespace" in headers on the other hand is evil, and should be
punishable by decapitation, yes.

0 new messages