File indexing completed on 2025-01-18 09:30:40
0001 #ifndef _DATE_TIME_TIME_PARSING_HPP___
0002 #define _DATE_TIME_TIME_PARSING_HPP___
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include "boost/tokenizer.hpp"
0013 #include "boost/lexical_cast.hpp"
0014 #include "boost/date_time/date_parsing.hpp"
0015 #include "boost/date_time/special_values_parser.hpp"
0016 #include "boost/cstdint.hpp"
0017 #include <iostream>
0018
0019 namespace boost {
0020 namespace date_time {
0021
0022
0023
0024
0025 template<class int_type>
0026 inline
0027 int_type power(int_type base, int_type exponent)
0028 {
0029 int_type result = 1;
0030 for(int i = 0; i < exponent; ++i){
0031 result *= base;
0032 }
0033 return result;
0034 }
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046 template<class time_duration, class char_type>
0047 inline
0048 time_duration
0049 str_from_delimited_time_duration(const std::basic_string<char_type>& s)
0050 {
0051 unsigned short min=0, sec =0;
0052 int hour =0;
0053 bool is_neg = (s.at(0) == '-');
0054 boost::int64_t fs=0;
0055 int pos = 0;
0056
0057 typedef typename std::basic_string<char_type>::traits_type traits_type;
0058 typedef boost::char_separator<char_type, traits_type> char_separator_type;
0059 typedef boost::tokenizer<char_separator_type,
0060 typename std::basic_string<char_type>::const_iterator,
0061 std::basic_string<char_type> > tokenizer;
0062 typedef typename boost::tokenizer<char_separator_type,
0063 typename std::basic_string<char_type>::const_iterator,
0064 typename std::basic_string<char_type> >::iterator tokenizer_iterator;
0065
0066 char_type sep_chars[5] = {'-',':',',','.'};
0067 char_separator_type sep(sep_chars);
0068 tokenizer tok(s,sep);
0069 for(tokenizer_iterator beg=tok.begin(); beg!=tok.end();++beg){
0070 switch(pos) {
0071 case 0: {
0072 hour = boost::lexical_cast<int>(*beg);
0073 break;
0074 }
0075 case 1: {
0076 min = boost::lexical_cast<unsigned short>(*beg);
0077 break;
0078 }
0079 case 2: {
0080 sec = boost::lexical_cast<unsigned short>(*beg);
0081 break;
0082 }
0083 case 3: {
0084 int digits = static_cast<int>(beg->length());
0085
0086
0087 #if (defined(BOOST_MSVC) && (_MSC_VER < 1300))
0088
0089
0090
0091 time_duration td(hour,min,sec,fs);
0092 int precision = td.num_fractional_digits();
0093
0094 if(digits >= precision) {
0095
0096 fs = _atoi64(beg->substr(0, precision).c_str());
0097 }
0098 else {
0099 fs = _atoi64(beg->c_str());
0100 }
0101 #else
0102 int precision = time_duration::num_fractional_digits();
0103 if(digits >= precision) {
0104
0105 fs = boost::lexical_cast<boost::int64_t>(beg->substr(0, precision));
0106 }
0107 else {
0108 fs = boost::lexical_cast<boost::int64_t>(*beg);
0109 }
0110 #endif
0111 if(digits < precision){
0112
0113
0114
0115 fs *= power(10, precision - digits);
0116 }
0117
0118 break;
0119 }
0120 default: break;
0121 }
0122 pos++;
0123 }
0124 if(is_neg) {
0125 return -time_duration(hour, min, sec, fs);
0126 }
0127 else {
0128 return time_duration(hour, min, sec, fs);
0129 }
0130 }
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142 template<class time_duration>
0143 inline
0144 time_duration
0145 parse_delimited_time_duration(const std::string& s)
0146 {
0147 return str_from_delimited_time_duration<time_duration,char>(s);
0148 }
0149
0150
0151 inline
0152 bool
0153 split(const std::string& s,
0154 char sep,
0155 std::string& first,
0156 std::string& second)
0157 {
0158 std::string::size_type sep_pos = s.find(sep);
0159 first = s.substr(0,sep_pos);
0160 if (sep_pos!=std::string::npos)
0161 second = s.substr(sep_pos+1);
0162 return true;
0163 }
0164
0165
0166 template<class time_type>
0167 inline
0168 time_type
0169 parse_delimited_time(const std::string& s, char sep)
0170 {
0171 typedef typename time_type::time_duration_type time_duration;
0172 typedef typename time_type::date_type date_type;
0173
0174
0175 std::string date_string, tod_string;
0176 split(s, sep, date_string, tod_string);
0177
0178 date_type d = parse_date<date_type>(date_string);
0179
0180 time_duration td = parse_delimited_time_duration<time_duration>(tod_string);
0181
0182 return time_type(d, td);
0183
0184 }
0185
0186
0187 template<class time_duration>
0188 inline
0189 time_duration
0190 parse_undelimited_time_duration(const std::string& s)
0191 {
0192 int precision = 0;
0193 {
0194
0195
0196
0197 time_duration tmp(0,0,0,1);
0198 precision = tmp.num_fractional_digits();
0199 }
0200
0201 int offsets[] = {2,2,2, precision+1};
0202 int pos = 0, sign = 0;
0203 int hours = 0;
0204 short min=0, sec=0;
0205 boost::int64_t fs=0;
0206
0207 if(s.at(sign) == '-')
0208 {
0209 ++sign;
0210 }
0211
0212
0213 std::string remain = s.substr(sign);
0214
0215
0216
0217
0218
0219 bool wrap_off = false;
0220 bool ret_part = true;
0221 boost::offset_separator osf(offsets, offsets+4, wrap_off, ret_part);
0222 typedef boost::tokenizer<boost::offset_separator,
0223 std::basic_string<char>::const_iterator,
0224 std::basic_string<char> > tokenizer;
0225 typedef boost::tokenizer<boost::offset_separator,
0226 std::basic_string<char>::const_iterator,
0227 std::basic_string<char> >::iterator tokenizer_iterator;
0228 tokenizer tok(remain, osf);
0229 for(tokenizer_iterator ti=tok.begin(); ti!=tok.end();++ti){
0230 switch(pos) {
0231 case 0:
0232 {
0233 hours = boost::lexical_cast<int>(*ti);
0234 break;
0235 }
0236 case 1:
0237 {
0238 min = boost::lexical_cast<short>(*ti);
0239 break;
0240 }
0241 case 2:
0242 {
0243 sec = boost::lexical_cast<short>(*ti);
0244 break;
0245 }
0246 case 3:
0247 {
0248 std::string char_digits(ti->substr(1));
0249 int digits = static_cast<int>(char_digits.length());
0250
0251
0252
0253 #if (defined(BOOST_MSVC) && (_MSC_VER <= 1200))
0254
0255 if(digits >= precision) {
0256
0257 fs = _atoi64(char_digits.substr(0, precision).c_str());
0258 }
0259 else if(digits == 0) {
0260 fs = 0;
0261 }
0262 else {
0263 fs = _atoi64(char_digits.c_str());
0264 }
0265 #else
0266 if(digits >= precision) {
0267
0268 fs = boost::lexical_cast<boost::int64_t>(char_digits.substr(0, precision));
0269 }
0270 else if(digits == 0) {
0271 fs = 0;
0272 }
0273 else {
0274 fs = boost::lexical_cast<boost::int64_t>(char_digits);
0275 }
0276 #endif
0277 if(digits < precision){
0278
0279
0280
0281 fs *= power(10, precision - digits);
0282 }
0283
0284 break;
0285 }
0286 default: break;
0287 }
0288 pos++;
0289 }
0290 if(sign) {
0291 return -time_duration(hours, min, sec, fs);
0292 }
0293 else {
0294 return time_duration(hours, min, sec, fs);
0295 }
0296 }
0297
0298
0299 template<class time_type>
0300 inline
0301 time_type
0302 parse_iso_time(const std::string& s, char sep)
0303 {
0304 typedef typename time_type::time_duration_type time_duration;
0305 typedef typename time_type::date_type date_type;
0306 typedef special_values_parser<date_type, std::string::value_type> svp_type;
0307
0308
0309
0310
0311
0312 if (svp_type::should_call_match(s)) {
0313 typedef typename svp_type::stringstream_type ss_type;
0314 typedef typename svp_type::stream_itr_type itr_type;
0315 typedef typename svp_type::match_results mr_type;
0316 svp_type p;
0317 mr_type mr;
0318 ss_type ss(s);
0319 itr_type itr(ss);
0320 itr_type end;
0321 if (p.match(itr, end, mr)) {
0322 return time_type(static_cast<special_values>(mr.current_match));
0323 }
0324 }
0325
0326
0327 std::string date_string, tod_string;
0328 split(s, sep, date_string, tod_string);
0329
0330 date_type d = parse_undelimited_date<date_type>(date_string);
0331
0332 time_duration td = parse_undelimited_time_duration<time_duration>(tod_string);
0333
0334 return time_type(d, td);
0335 }
0336
0337 } }
0338
0339 #endif