format_date_parser.hpp

来自「CGAL is a collaborative effort of severa」· HPP 代码 · 共 285 行

HPP
285
字号
#ifndef DATE_TIME_FORMAT_DATE_PARSER_HPP__#define DATE_TIME_FORMAT_DATE_PARSER_HPP__/* Copyright (c) 2004 CrystalClear Software, Inc. * Use, modification and distribution is subject to the  * Boost Software License, Version 1.0. (See accompanying * file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) * Author: Jeff Garland * $Date: 2004/11/20 10:36:24 $ */#include "boost/lexical_cast.hpp"#include "boost/algorithm/string.hpp" //todo narrow this#include "boost/date_time/string_parse_tree.hpp"#include "boost/date_time/strings_from_facet.hpp"#include <string>#include <vector>namespace boost { namespace date_time {//!Helper function for parsing fixed length strings into integerstemplate<typename int_type, typename charT>inlineint_typefixed_string_to_int(std::istreambuf_iterator<charT>& itr,                    unsigned int length){  typedef std::basic_string<charT>  string_type;  unsigned int j = 0;  string_type s;  while (j < length) {    s += (*itr);    itr++;    j++;  }  int_type i = boost::lexical_cast<int_type>(s);  return i;}//!Helper function for parsing fixed length strings into integerstemplate<typename int_type, typename charT>inlineint_typevar_string_to_int(std::istreambuf_iterator<charT>& itr,                  unsigned int max_length){  typedef std::basic_string<charT>  string_type;  unsigned int j = 0;  string_type s;  while ((j < max_length) && std::isdigit(*itr)) {    s += (*itr);    itr++;    j++;  }  int_type i = boost::lexical_cast<int_type>(s);  return i;}//! Class with generic date parsing using a format string/*! The following is the set of recognized format specifiers -  %a - Short weekday name -  %A - Long weekday name -  %b - Abbreviated month name -  %B - Full month name -  %d - Day of the month as decimal -  %j - Day of year as decimal from 1 to 366 -  %m - Month name as a decimal 01 to 12 -  %U - Week number 00 to 53 with first Sunday as the first day of week 1? -  %w - Weekday as decimal number 0 to 6 where Sunday == 0 -  %W - Week number 00 to 53 where Monday is first day of week 1 -  %x - facet default date representation -  %y - Year without the century - eg: 04 for 2004 -  %Y - Year with century  The weekday specifiers (%a and %A) do not add to the date construction, but they provide a way to skip over the weekday names for formats that provide them. todo -- Another interesting feature that this approach could provide is         an option to fill in any missing fields with the current values         from the clock.  So if you have %m-%d the parser would detect         the missing year value and fill it in using the clock.  todo -- What to do with the %x.  %x in the classic facet is just bad... */template<class date_type, typename charT>class format_date_parser{ public:  typedef std::basic_string<charT>        string_type;  typedef std::basic_stringstream<charT>  stringstream_type;  typedef std::istreambuf_iterator<charT> stream_itr_type;  typedef typename string_type::const_iterator const_itr;  typedef typename date_type::year_type  year_type;  typedef typename date_type::month_type month_type;  typedef typename date_type::duration_type duration_type;  typedef string_parse_tree<charT> parse_tree_type;  typedef typename parse_tree_type::parse_match_result_type match_results;  typedef std::vector<std::basic_string<charT> > input_collection_type;    format_date_parser(const string_type& format,                     const input_collection_type& month_short_names,                     const input_collection_type& month_long_names,                     const input_collection_type& weekday_short_names,                     const input_collection_type& weekday_long_names) :    m_format(format),    m_month_short_names(month_short_names),    m_month_long_names(month_long_names),    m_weekday_short_names(weekday_short_names),    m_weekday_long_names(weekday_long_names)  {}    format_date_parser(const string_type& format,                     const std::locale& locale) :    m_format(format),    m_month_short_names(gather_month_strings<charT>(locale)),    m_month_long_names(gather_month_strings<charT>(locale, false)),    m_weekday_short_names(gather_weekday_strings<char>(locale)),    m_weekday_long_names(gather_weekday_strings<char>(locale, false))  {}    string_type format() const  {    return m_format;  }  void format(string_type format)  {    m_format = format;  }  date_type  parse_date(const string_type& value,              const string_type& format) const  {    stringstream_type ss;    ss << value;     stream_itr_type sitr(ss);    stream_itr_type stream_end;    return parse_date(sitr, stream_end, format);  }  date_type  parse_date(std::istreambuf_iterator<charT>& sitr,              std::istreambuf_iterator<charT>& stream_end) const  {    parse_date(sitr, stream_end, m_format);  }  date_type  parse_date(std::istreambuf_iterator<charT>& sitr,              std::istreambuf_iterator<charT>& stream_end,             string_type format) const  {    bool use_current_char = false;    charT current_char = *sitr;    unsigned short year(0), month(0), day(0), day_of_year(0);        const_itr itr(format.begin());    while (itr != format.end() && (sitr != stream_end)) {      if (*itr == '%') {        itr++;        if (*itr != '%') { //ignore '%%'          unsigned short i = 0;          switch(*itr) {          case 'a':             {              //this value is just throw away.  It could be used for              //error checking potentially, but it isn't helpful in               //actually constructing the date - we just need to get it              //out of the stream              match_results mr = m_weekday_short_names.match(sitr, stream_end);              unsigned int wkday = mr.current_match;              if (mr.has_remaining()) {                current_char = mr.last_char();                use_current_char = true;              }              break;            }          case 'A':             {              //this value is just throw away.  It could be used for              //error checking potentially, but it isn't helpful in               //actually constructing the date - we just need to get it              //out of the stream              match_results mr = m_weekday_long_names.match(sitr, stream_end);              unsigned int wkday = mr.current_match;              if (mr.has_remaining()) {                current_char = mr.last_char();                use_current_char = true;              }              break;            }          case 'b':             {              match_results mr = m_month_short_names.match(sitr, stream_end);              month = mr.current_match;              if (mr.has_remaining()) {                current_char = mr.last_char();                use_current_char = true;              }              break;            }          case 'B':             {              match_results mr = m_month_long_names.match(sitr, stream_end);              month = mr.current_match;              if (mr.has_remaining()) {                current_char = mr.last_char();                use_current_char = true;              }              break;            }          case 'd':             {              day = var_string_to_int<unsigned short, charT>(sitr, 2);              break;            }          case 'j':             {              day_of_year = fixed_string_to_int<unsigned short, charT>(sitr, 3);              break;            }          case 'm':             {              month = var_string_to_int<unsigned short, charT>(sitr, 2);              break;            }          case 'Y':             {              year = fixed_string_to_int<unsigned short, charT>(sitr, 4);              break;            }          case 'y':             {              year = fixed_string_to_int<unsigned short, charT>(sitr, 2);              year += 2000; //make 2 digit years in this century              break;            }          default:            {} //ignore those we don't understand                      }//switch                  }                itr++; //advance past format specifier      }      else {  //skip past chars in format and in buffer        itr++;        if (use_current_char) {          use_current_char = false;          current_char = *sitr;        }        else {          sitr++;        }      }    }        if (day_of_year != 0) {      date_type d(year-1,12,31); //end of prior year      return d + duration_type(day_of_year);    }    return date_type(year, month, day);  }     private:  string_type m_format;  parse_tree_type m_month_short_names;  parse_tree_type m_month_long_names;  parse_tree_type m_weekday_short_names;  parse_tree_type m_weekday_long_names;};} } //namespace#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?