[date_time] howto determine date format?

Hi! With the code below I try to automagically determine the date format found in input files. I'd expect the code below to find the date format "%d.%m.%Y" for "05.02.2008", but I got surprised by obtaining "%m/%d/%Y". A major pain it is with those dates. Whether my shallow knowledge of locales and imbue or boost::date_time (from boost-1.37.0) is to be blamed is beyond my horizon. I feel like date accepts '.' where I said "expect '/'", so I think this should be changed. I may be wrong. Could you please shed some light on the issue? Thanks, Markus #include <boost/assign/list_of.hpp> #include <boost/date_time/posix_time/posix_time.hpp> #include <boost/date_time/gregorian/gregorian.hpp> #include <boost/date_time/local_time/local_time.hpp> #include <boost/foreach.hpp> #include <boost/algorithm/string.hpp> #include <string> #include <list> inline std::string determine_date_format(std::string const & s) { using namespace boost::assign; using namespace boost::gregorian; std::list<std::string> possible_formats = // TODO: add others here! list_of ("%Y-%m-%d")("%Y/%m/%d")("%m/%d/%Y")("%d.%m.%Y"); bool inform_user = false; BOOST_FOREACH(std::string const & format, possible_formats) { if (inform_user) { std::cout << "Trying format '" << format << "' ..." << std::endl; } try { date_input_facet * input_facet = new date_input_facet(format.c_str()); std::istringstream iss(s); iss.imbue(std::locale(iss.getloc(), input_facet)); date d(not_a_date_time); iss >> d; if (!iss.fail() && (!d.is_not_a_date())) { return format; } std::cout << "WARNING: date format '" << format << "' does not match '" << s << "'." << std::endl; inform_user = true; } catch(...) { } } std::cout << "WARNING: date format not recognized. " << "Please reconfigure your measurement equipment " << "to ISO standard output!" << std::endl; return ""; } int main() { std::string the_date = "05.02.2008"; std::string format = determine_date_format(the_date); std::cout << the_date << " has date-time-format " << format << std::endl; return 0; }

BOOST_FOREACH(std: :string const
%20format,%20possible_formats)%0A>%20%20%20%20%20%7B%0A>%20%20%20%20%20%20%20%20%20if%20(inform_user)%0A>%20%20%20%20%20%20%20%20%20%7B%0A>%20%20%20%20%20%20%20%20%20%20%20%20%20std: :cout%20<<%20%22Trying%20format%20'%22%20<<%20format%20<<%20%22'%20...%22%20<<%20std::endl;%20%0A>%20%20%20%20%20%20%20%20%20%7D%20%0A>%20%0A>%20%20%20%20%20%20%20%20%20try%0A>%20%20%20%20%20%20%20%20%20%7B%0A>%20%20%20%20%20%20%20%20%20%20%20%20%20date_input_facet%20*%20input_facet%20:
std: :istringstream iss(s); iss.imbue(std: :locale(iss.getloc(), input_facet));
Content-type: text/plain; charset=UTF-8 Date: Thu, 15 Apr 2010 23:47:31 -0400 Message-id: <1271389651.25933.26.camel@localhost> MIME-version: 1.0 X-Mailer: Evolution 2.28.3 (2.28.3-1.fc12) Content-transfer-encoding: 7bit On 2010-02-24 14:08, Markus Werle wrote:
Hi!
With the code below I try to automagically determine the date format found in input files. I'd expect the code below to find the date format "%d.%m.%Y" for "05.02.2008", but I got surprised by obtaining "%m/%d/%Y". A major pain it is with those dates. Whether my shallow knowledge of locales and imbue or boost::date_time (from boost-1.37.0) is to be blamed is beyond my horizon.
I feel like date accepts '.' where I said "expect '/'", so I think this should be changed. I may be wrong.
Could you please shed some light on the issue?
Thanks, Markus
#include <boost/assign/list_of.hpp>
#include <boost/date_time/posix_time/posix_time.hpp> #include <boost/date_time/gregorian/gregorian.hpp> #include <boost/date_time/local_time/local_time.hpp> #include <boost/foreach.hpp> #include <boost/algorithm/string.hpp>
#include <string> #include <list>
inline std::string determine_date_format(std::string const
I'm having the similar problems, with similar code. It's aggravating. Oh, yeah, I have boost-1.39.0-9.fc12.x86_64. This is what happens when I run the executable: echo "1230735660" | ./dateIO 5660-Dec-07 00:00:00 %m/%d/%Y %H:%M:%S It thinks 1230735660 is in the format %m/%d/%Y %H:%M:%S, as if 3 were the separator, which then produces m=12, d=07 and Y=5660. How come? If I want / to be the separator, then / should be the separator, not 3. And this is the code: // g++ -g -Wall -o dateIO dateIO.C -lboost_date_time #include <iostream> #include <sstream> #include <cstdlib> #include <string> #include <boost/date_time/posix_time/posix_time.hpp> using namespace boost::posix_time; using namespace std; // Known date formats. const char * knownFormats[]={ "%Y-%m-%d %H:%M:%S", "%Y-%m-%d, %H:%M:%S", "%Y/%m/%d %H:%M:%S", "%Y/%m/%d, %H:%M:%S", "%m/%d/%Y %H:%M:%S", "%m/%d/%Y, %H:%M:%S", "%m-%d-%Y %H:%M:%S", "%m-%d-%Y, %H:%M:%S", "%b %d, %Y %H:%M:%S", "%Y-%b-%d %H:%M:%S", "%Y-%b-%d, %H:%M:%S", 0 }; ptime readDateGivenFormat(istream & IN, const char * fmt) { ptime pt(not_a_date_time); // Always allocate facet with new! Only locale can destroy it because // facet's destructor is not public (and locale is a friend). // // Thank you Angelika Langer! Long live Angelika Langer! //http://www.angelikalanger.com/Conferences/Slides/CppLocales-ACCU-2001.pdf time_input_facet * tifacet = new time_input_facet(fmt); locale loc(IN.getloc(),tifacet); IN.imbue(loc); IN >> pt; return pt; } int datestr2ptime(const char * datestr, ptime & pt) { istringstream * INSTR=0; int i=0; pt=ptime(not_a_date_time); // Can't read it in a loop from stdin, because once read, // it won't be read again! // Keep creating a new istringstream bound to datestr for each // known format. while(knownFormats[i]!=0){ // Put it into INSTR - each time with new! INSTR = new istringstream(datestr); pt=readDateGivenFormat(*INSTR, knownFormats[i]); delete INSTR; if(pt!=not_a_date_time) return i; i++; } return i; } int main(int argc, char * argv[]) { ptime pt(not_a_date_time); string datestr; int i=-1; getline(cin,datestr); i=datestr2ptime(datestr.c_str(), pt); cout << pt; if(knownFormats[i]) cout << "\t" << knownFormats[i]; cout << endl; return 0; }
participants (2)
-
Amadeus W.M.
-
Markus Werle