diff --git a/include/boost/date_time/date_parsing.hpp b/include/boost/date_time/date_parsing.hpp index b0ed4d6..9725f2d 100644 --- a/include/boost/date_time/date_parsing.hpp +++ b/include/boost/date_time/date_parsing.hpp @@ -3,12 +3,16 @@ #define _DATE_TIME_DATE_PARSING_HPP___ /* Copyright (c) 2002, 2003 CrystalClear Software, Inc. * Disclaimer & Full Copyright at end of file - * Author: Jeff Garland + * Author: Jeff Garland, Bart Garst */ #include "boost/tokenizer.hpp" #include "boost/lexical_cast.hpp" +#include "boost/date_time/compiler_config.hpp" +#include #include +#include +#include namespace boost { @@ -16,12 +20,15 @@ namespace date_time { //! Generic function to parse a delimited date (eg: 2002-02-10) /*! Accepted formats are: "2003-02-10" or " 2003-Feb-10" or - * "2003-Feburary-10" */ + * "2003-Feburary-10" + * Note: Month names may be case in-sensitive, check compiler_config.hpp + * to see if case insensitivity is suppoerted for your compiler */ template date_type parse_date(const std::string& s) { typedef typename date_type::year_type year_type; + typedef typename date_type::month_type month_type; int pos = 0; typename date_type::ymd_type ymd(year_type::min(),1,1); boost::tokenizer > tok(s); @@ -44,15 +51,20 @@ namespace date_time { } else { - for(int j = 1; j <= 12; ++j) - { - typedef gregorian::greg_month::month_enum month_enum; - gregorian::greg_month m(static_cast(j)); - if(s == m.as_long_string() || s == m.as_short_string()) - { - i = static_cast(j); - break; - } + typename month_type::month_map_ptr_type ptr = month_type::get_month_map_ptr(); +#if defined(BOOST_DATE_TIME_NO_STD_TRANSFORM) +#else + std::transform(s.begin(), s.end(), + s.begin(), + tolower); +#endif + typename month_type::month_map_type::iterator iter = ptr->find(s); + if(iter != ptr->end()) // required for STLport + { + i = iter->second; + } + else{ + i = 13; // intentionally out of range - name not found } } ymd.month = i; @@ -95,28 +107,66 @@ namespace date_time { } - template - date_type - parse_date2(const std::string& s) + //! Helper function for 'date gregorian::from_stream()' + /*! Creates a string from the iterators that reference the + * begining & end of a char[] or string. All elements are + * used in output string */ + template + inline std::string from_stream_type(iterator_type& beg, iterator_type& end, + char) { - //using namespace boost; - int pos = 0; - typedef typename date_type::year_type year_type; - typename date_type::ymd_type ymd(year_type::min(),1,1); - boost::char_delimiters_separator delim("DT"); - boost::tokenizer > tok(s); - for(boost::tokenizer<>::iterator beg=tok.begin(); beg!=tok.end();++beg){ - int i = boost::lexical_cast(*beg); - switch(pos) { - case 0: ymd.year = i; break; - case 1: ymd.month = i; break; - case 2: ymd.day = i; break; - }; - pos++; + std::stringstream ss(""); + while(beg != end) + { + ss << *beg++; } - return date_type(ymd); + return ss.str(); + } + //! Helper function for 'date gregorian::from_stream()' + /*! Returns the first string found in the stream referenced by the + * begining & end iterators */ + template + inline std::string from_stream_type(iterator_type& beg, iterator_type& end, + std::string) + { + return *beg; } + /* I believe the wchar stuff would be best elsewhere, perhaps in + * parse_date<>()? In the mean time this gets us started... */ + //! Helper function for 'date gregorian::from_stream()' + /*! Creates a string from the iterators that reference the + * begining & end of a wstring. All elements are + * used in output string */ + template + inline std::string from_stream_type(iterator_type& beg, iterator_type& end, + wchar_t) + { + std::stringstream ss(""); + while(beg != end) + { + ss << ss.narrow(*beg++, 'X'); // 'X' will cause exception to be thrown + } + return ss.str(); + } +#ifndef BOOST_NO_STD_WSTRING + //! Helper function for 'date gregorian::from_stream()' + /*! Creates a string from the first wstring found in the stream + * referenced by the begining & end iterators */ + template + inline std::string from_stream_type(iterator_type& beg, iterator_type& end, + std::wstring) + { + std::wstring ws = *beg; + std::stringstream ss(""); + std::wstring::iterator wsb = ws.begin(), wse = ws.end(); + while(wsb != wse) + { + ss << ss.narrow(*wsb++, 'X'); // 'X' will cause exception to be thrown + } + return ss.str(); + } +#endif // BOOST_NO_STD_WSTRING } } //namespace date_time diff --git a/include/boost/date_time/gregorian/greg_month.hpp b/include/boost/date_time/gregorian/greg_month.hpp index edbf261..310c693 100644 --- a/include/boost/date_time/gregorian/greg_month.hpp +++ b/include/boost/date_time/gregorian/greg_month.hpp @@ -7,9 +7,13 @@ #include "boost/date_time/constrained_value.hpp" #include "boost/date_time/date_defs.hpp" +#include "boost/shared_ptr.hpp" +#include "boost/date_time/compiler_config.hpp" #include #include - +#include +#include +#include namespace boost { namespace gregorian { @@ -47,6 +51,8 @@ namespace gregorian { class greg_month : public greg_month_rep { public: typedef date_time::months_of_year month_enum; + typedef std::map month_map_type; + typedef boost::shared_ptr month_map_ptr_type; //! Construct a month from the months_of_year enumeration greg_month(month_enum theMonth) : greg_month_rep(static_cast(theMonth)) {} @@ -59,6 +65,8 @@ namespace gregorian { month_enum as_enum() const {return static_cast(value_);} const char* as_short_string() const; const char* as_long_string() const; + //! Shared pointer to a map of Month strings (Names & Abbrev) & numbers + static month_map_ptr_type get_month_map_ptr(); }; } } //namespace gregorian diff --git a/include/boost/date_time/gregorian/parsers.hpp b/include/boost/date_time/gregorian/parsers.hpp index 3850c3e..264f0f1 100644 --- a/include/boost/date_time/gregorian/parsers.hpp +++ b/include/boost/date_time/gregorian/parsers.hpp @@ -2,21 +2,45 @@ #define GREGORIAN_PARSERS_HPP___ /* Copyright (c) 2002 CrystalClear Software, Inc. * Disclaimer & Full Copyright at end of file - * Author: Jeff Garland + * Author: Jeff Garland, Bart Garst */ #include "boost/date_time/gregorian/gregorian_types.hpp" #include "boost/date_time/date_parsing.hpp" - +#include "boost/date_time/compiler_config.hpp" +#include +#include namespace boost { namespace gregorian { - //! From delimited date string where with order year-month-day eg: 2002-1-25 + //! Deprecated: Use from_simple_string inline date from_string(std::string s) { return date_time::parse_date(s); } + //! From delimited date string where with order year-month-day eg: 2002-1-25 or 2003-Jan-25 + inline date from_simple_string(std::string s) { + return date_time::parse_date(s); + } + +#if !(defined(BOOST_NO_STD_ITERATOR_TRAITS)) + //! Stream should hold a date in the form of: 2002-1-25. Month number, abbrev, or name are accepted + /* Arguments passed in by-value for convertability of char[] + * to iterator_type. Calls to from_stream_type are by-reference + * since conversion is already done */ + template + inline date from_stream(iterator_type beg, iterator_type end) { + if(beg == end) + { + return date(not_a_date_time); + } + std::string s = date_time::from_stream_type(beg, end, + std::iterator_traits::value_type()); + return date_time::parse_date(s); + } +#endif //BOOST_NO_STD_ITERATOR_TRAITS + //! From iso type date string where with order year-month-day eg: 20020125 inline date from_undelimited_string(std::string s) { return date_time::parse_undelimited_date(s);