Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/date_time/time_facet.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children | c530137014c0 |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
1 | |
2 #ifndef _DATE_TIME_FACET__HPP__ | |
3 #define _DATE_TIME_FACET__HPP__ | |
4 | |
5 /* Copyright (c) 2004-2005 CrystalClear Software, Inc. | |
6 * Use, modification and distribution is subject to the | |
7 * Boost Software License, Version 1.0. (See accompanying | |
8 * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) | |
9 * Author: Martin Andrian, Jeff Garland, Bart Garst | |
10 * $Date: 2013-10-15 08:22:02 -0700 (Tue, 15 Oct 2013) $ | |
11 */ | |
12 | |
13 #include <cctype> | |
14 #include <locale> | |
15 #include <limits> | |
16 #include <string> | |
17 #include <sstream> | |
18 #include <iomanip> | |
19 #include <iterator> // i/ostreambuf_iterator | |
20 #include <exception> | |
21 #include <boost/assert.hpp> | |
22 #include <boost/lexical_cast.hpp> | |
23 #include <boost/throw_exception.hpp> | |
24 #include <boost/range/as_literal.hpp> | |
25 #include <boost/algorithm/string/erase.hpp> | |
26 #include <boost/algorithm/string/replace.hpp> | |
27 #include <boost/date_time/compiler_config.hpp> | |
28 #include <boost/date_time/date_facet.hpp> | |
29 #include <boost/date_time/string_convert.hpp> | |
30 #include <boost/date_time/special_defs.hpp> | |
31 #include <boost/date_time/time_resolution_traits.hpp> // absolute_value | |
32 | |
33 namespace boost { | |
34 namespace date_time { | |
35 | |
36 template <class CharT> | |
37 struct time_formats { | |
38 public: | |
39 typedef CharT char_type; | |
40 static const char_type fractional_seconds_format[3]; // f | |
41 static const char_type fractional_seconds_or_none_format[3]; // F | |
42 static const char_type seconds_with_fractional_seconds_format[3]; // s | |
43 static const char_type seconds_format[3]; // S | |
44 static const char_type hours_format[3]; // H | |
45 static const char_type unrestricted_hours_format[3]; // O | |
46 static const char_type full_24_hour_time_format[3]; // T | |
47 static const char_type full_24_hour_time_expanded_format[9]; // HH:MM:SS | |
48 static const char_type short_24_hour_time_format[3]; // R | |
49 static const char_type short_24_hour_time_expanded_format[6]; // HH:MM | |
50 static const char_type standard_format[9]; // x X | |
51 static const char_type zone_abbrev_format[3]; // z | |
52 static const char_type zone_name_format[3]; // Z | |
53 static const char_type zone_iso_format[3]; // q | |
54 static const char_type zone_iso_extended_format[3]; // Q | |
55 static const char_type posix_zone_string_format[4]; // ZP | |
56 static const char_type duration_sign_negative_only[3]; // - | |
57 static const char_type duration_sign_always[3]; // + | |
58 static const char_type duration_seperator[2]; | |
59 static const char_type negative_sign[2]; //- | |
60 static const char_type positive_sign[2]; //+ | |
61 static const char_type iso_time_format_specifier[18]; | |
62 static const char_type iso_time_format_extended_specifier[22]; | |
63 //default ptime format is YYYY-Mon-DD HH:MM:SS[.fff...][ zzz] | |
64 static const char_type default_time_format[23]; | |
65 // default_time_input_format uses a posix_time_zone_string instead of a time zone abbrev | |
66 static const char_type default_time_input_format[24]; | |
67 //default time_duration format is HH:MM:SS[.fff...] | |
68 static const char_type default_time_duration_format[11]; | |
69 }; | |
70 | |
71 template <class CharT> | |
72 const typename time_formats<CharT>::char_type | |
73 time_formats<CharT>::fractional_seconds_format[3] = {'%','f'}; | |
74 | |
75 template <class CharT> | |
76 const typename time_formats<CharT>::char_type | |
77 time_formats<CharT>::fractional_seconds_or_none_format[3] = {'%','F'}; | |
78 | |
79 template <class CharT> | |
80 const typename time_formats<CharT>::char_type | |
81 time_formats<CharT>::seconds_with_fractional_seconds_format[3] = {'%','s'}; | |
82 | |
83 template <class CharT> | |
84 const typename time_formats<CharT>::char_type | |
85 time_formats<CharT>::seconds_format[3] = {'%','S'}; | |
86 | |
87 template <class CharT> | |
88 const typename time_formats<CharT>::char_type | |
89 time_formats<CharT>::hours_format[3] = {'%','H'}; | |
90 | |
91 template <class CharT> | |
92 const typename time_formats<CharT>::char_type | |
93 time_formats<CharT>::unrestricted_hours_format[3] = {'%','O'}; | |
94 | |
95 template <class CharT> | |
96 const typename time_formats<CharT>::char_type | |
97 time_formats<CharT>::full_24_hour_time_format[3] = {'%','T'}; | |
98 | |
99 template <class CharT> | |
100 const typename time_formats<CharT>::char_type | |
101 time_formats<CharT>::full_24_hour_time_expanded_format[9] = | |
102 {'%','H',':','%','M',':','%','S'}; | |
103 | |
104 template <class CharT> | |
105 const typename time_formats<CharT>::char_type | |
106 time_formats<CharT>::short_24_hour_time_format[3] = {'%','R'}; | |
107 | |
108 template <class CharT> | |
109 const typename time_formats<CharT>::char_type | |
110 time_formats<CharT>::short_24_hour_time_expanded_format[6] = | |
111 {'%','H',':','%','M'}; | |
112 | |
113 template <class CharT> | |
114 const typename time_formats<CharT>::char_type | |
115 //time_formats<CharT>::standard_format[5] = {'%','c',' ','%','z'}; | |
116 time_formats<CharT>::standard_format[9] = {'%','x',' ','%','X',' ','%','z'}; | |
117 | |
118 template <class CharT> | |
119 const typename time_formats<CharT>::char_type | |
120 time_formats<CharT>::zone_abbrev_format[3] = {'%','z'}; | |
121 | |
122 template <class CharT> | |
123 const typename time_formats<CharT>::char_type | |
124 time_formats<CharT>::zone_name_format[3] = {'%','Z'}; | |
125 | |
126 template <class CharT> | |
127 const typename time_formats<CharT>::char_type | |
128 time_formats<CharT>::zone_iso_format[3] = {'%','q'}; | |
129 | |
130 template <class CharT> | |
131 const typename time_formats<CharT>::char_type | |
132 time_formats<CharT>::zone_iso_extended_format[3] ={'%','Q'}; | |
133 | |
134 template <class CharT> | |
135 const typename time_formats<CharT>::char_type | |
136 time_formats<CharT>::posix_zone_string_format[4] ={'%','Z','P'}; | |
137 | |
138 template <class CharT> | |
139 const typename time_formats<CharT>::char_type | |
140 time_formats<CharT>::duration_seperator[2] = {':'}; | |
141 | |
142 template <class CharT> | |
143 const typename time_formats<CharT>::char_type | |
144 time_formats<CharT>::negative_sign[2] = {'-'}; | |
145 | |
146 template <class CharT> | |
147 const typename time_formats<CharT>::char_type | |
148 time_formats<CharT>::positive_sign[2] = {'+'}; | |
149 | |
150 template <class CharT> | |
151 const typename time_formats<CharT>::char_type | |
152 time_formats<CharT>::duration_sign_negative_only[3] ={'%','-'}; | |
153 | |
154 template <class CharT> | |
155 const typename time_formats<CharT>::char_type | |
156 time_formats<CharT>::duration_sign_always[3] ={'%','+'}; | |
157 | |
158 template <class CharT> | |
159 const typename time_formats<CharT>::char_type | |
160 time_formats<CharT>::iso_time_format_specifier[18] = | |
161 {'%', 'Y', '%', 'm', '%', 'd', 'T', | |
162 '%', 'H', '%', 'M', '%', 'S', '%', 'F', '%','q' }; | |
163 | |
164 template <class CharT> | |
165 const typename time_formats<CharT>::char_type | |
166 time_formats<CharT>::iso_time_format_extended_specifier[22] = | |
167 {'%', 'Y', '-', '%', 'm', '-', '%', 'd', ' ', | |
168 '%', 'H', ':', '%', 'M', ':', '%', 'S', '%', 'F','%','Q'}; | |
169 | |
170 template <class CharT> | |
171 const typename time_formats<CharT>::char_type | |
172 time_formats<CharT>::default_time_format[23] = | |
173 {'%','Y','-','%','b','-','%','d',' ', | |
174 '%','H',':','%','M',':','%','S','%','F',' ','%','z'}; | |
175 | |
176 template <class CharT> | |
177 const typename time_formats<CharT>::char_type | |
178 time_formats<CharT>::default_time_input_format[24] = | |
179 {'%','Y','-','%','b','-','%','d',' ', | |
180 '%','H',':','%','M',':','%','S','%','F',' ','%','Z','P'}; | |
181 | |
182 template <class CharT> | |
183 const typename time_formats<CharT>::char_type | |
184 time_formats<CharT>::default_time_duration_format[11] = | |
185 {'%','O',':','%','M',':','%','S','%','F'}; | |
186 | |
187 | |
188 | |
189 /*! Facet used for format-based output of time types | |
190 * This class provides for the use of format strings to output times. In addition | |
191 * to the flags for formatting date elements, the following are the allowed format flags: | |
192 * - %x %X => default format - enables addition of more flags to default (ie. "%x %X %z") | |
193 * - %f => fractional seconds ".123456" | |
194 * - %F => fractional seconds or none: like frac sec but empty if frac sec == 0 | |
195 * - %s => seconds w/ fractional sec "02.123" (this is the same as "%S%f) | |
196 * - %S => seconds "02" | |
197 * - %z => abbreviated time zone "EDT" | |
198 * - %Z => full time zone name "Eastern Daylight Time" | |
199 */ | |
200 template <class time_type, | |
201 class CharT, | |
202 class OutItrT = std::ostreambuf_iterator<CharT, std::char_traits<CharT> > > | |
203 class time_facet : | |
204 public boost::date_time::date_facet<typename time_type::date_type , CharT, OutItrT> { | |
205 typedef time_formats< CharT > formats_type; | |
206 public: | |
207 typedef typename time_type::date_type date_type; | |
208 typedef typename time_type::time_duration_type time_duration_type; | |
209 typedef boost::date_time::period<time_type,time_duration_type> period_type; | |
210 typedef boost::date_time::date_facet<typename time_type::date_type, CharT, OutItrT> base_type; | |
211 typedef typename base_type::string_type string_type; | |
212 typedef typename base_type::char_type char_type; | |
213 typedef typename base_type::period_formatter_type period_formatter_type; | |
214 typedef typename base_type::special_values_formatter_type special_values_formatter_type; | |
215 typedef typename base_type::date_gen_formatter_type date_gen_formatter_type; | |
216 static const char_type* fractional_seconds_format; // %f | |
217 static const char_type* fractional_seconds_or_none_format; // %F | |
218 static const char_type* seconds_with_fractional_seconds_format; // %s | |
219 static const char_type* seconds_format; // %S | |
220 static const char_type* hours_format; // %H | |
221 static const char_type* unrestricted_hours_format; // %O | |
222 static const char_type* standard_format; // %x X | |
223 static const char_type* zone_abbrev_format; // %z | |
224 static const char_type* zone_name_format; // %Z | |
225 static const char_type* zone_iso_format; // %q | |
226 static const char_type* zone_iso_extended_format; // %Q | |
227 static const char_type* posix_zone_string_format; // %ZP | |
228 static const char_type* duration_seperator; | |
229 static const char_type* duration_sign_always; // %+ | |
230 static const char_type* duration_sign_negative_only; // %- | |
231 static const char_type* negative_sign; //- | |
232 static const char_type* positive_sign; //+ | |
233 static const char_type* iso_time_format_specifier; | |
234 static const char_type* iso_time_format_extended_specifier; | |
235 | |
236 //default ptime format is YYYY-Mon-DD HH:MM:SS[.fff...][ zzz] | |
237 static const char_type* default_time_format; | |
238 //default time_duration format is HH:MM:SS[.fff...] | |
239 static const char_type* default_time_duration_format; | |
240 static std::locale::id id; | |
241 | |
242 #if defined (__SUNPRO_CC) && defined (_RWSTD_VER) | |
243 std::locale::id& __get_id (void) const { return id; } | |
244 #endif | |
245 | |
246 //! sets default formats for ptime, local_date_time, and time_duration | |
247 explicit time_facet(::size_t ref_arg = 0) | |
248 : base_type(default_time_format, period_formatter_type(), special_values_formatter_type(), date_gen_formatter_type(), ref_arg), | |
249 m_time_duration_format(string_type(duration_sign_negative_only) + default_time_duration_format) | |
250 {} | |
251 | |
252 //! Construct the facet with an explicitly specified format | |
253 explicit time_facet(const char_type* format_arg, | |
254 period_formatter_type period_formatter_arg = period_formatter_type(), | |
255 const special_values_formatter_type& special_value_formatter = special_values_formatter_type(), | |
256 date_gen_formatter_type dg_formatter = date_gen_formatter_type(), | |
257 ::size_t ref_arg = 0) | |
258 : base_type(format_arg, | |
259 period_formatter_arg, | |
260 special_value_formatter, | |
261 dg_formatter, | |
262 ref_arg), | |
263 m_time_duration_format(string_type(duration_sign_negative_only) + default_time_duration_format) | |
264 {} | |
265 | |
266 //! Changes format for time_duration | |
267 void time_duration_format(const char_type* const format) | |
268 { | |
269 m_time_duration_format = format; | |
270 } | |
271 | |
272 virtual void set_iso_format() | |
273 { | |
274 this->m_format = iso_time_format_specifier; | |
275 } | |
276 virtual void set_iso_extended_format() | |
277 { | |
278 this->m_format = iso_time_format_extended_specifier; | |
279 } | |
280 | |
281 OutItrT put(OutItrT next_arg, | |
282 std::ios_base& ios_arg, | |
283 char_type fill_arg, | |
284 const time_type& time_arg) const | |
285 { | |
286 if (time_arg.is_special()) { | |
287 return this->do_put_special(next_arg, ios_arg, fill_arg, | |
288 time_arg.date().as_special()); | |
289 } | |
290 string_type local_format(this->m_format); | |
291 | |
292 // %T and %R have to be replaced here since they are not standard | |
293 boost::algorithm::replace_all(local_format, | |
294 boost::as_literal(formats_type::full_24_hour_time_format), | |
295 boost::as_literal(formats_type::full_24_hour_time_expanded_format)); | |
296 boost::algorithm::replace_all(local_format, | |
297 boost::as_literal(formats_type::short_24_hour_time_format), | |
298 boost::as_literal(formats_type::short_24_hour_time_expanded_format)); | |
299 | |
300 string_type frac_str; | |
301 if (local_format.find(seconds_with_fractional_seconds_format) != string_type::npos) { | |
302 // replace %s with %S.nnn | |
303 frac_str = | |
304 fractional_seconds_as_string(time_arg.time_of_day(), false); | |
305 char_type sep = std::use_facet<std::numpunct<char_type> >(ios_arg.getloc()).decimal_point(); | |
306 | |
307 string_type replace_string(seconds_format); | |
308 replace_string += sep; | |
309 replace_string += frac_str; | |
310 boost::algorithm::replace_all(local_format, | |
311 seconds_with_fractional_seconds_format, | |
312 replace_string); | |
313 } | |
314 /* NOTE: replacing posix_zone_string_format must be done BEFORE | |
315 * zone_name_format: "%ZP" & "%Z", if Z is checked first it will | |
316 * incorrectly replace a zone_name where a posix_string should go */ | |
317 if (local_format.find(posix_zone_string_format) != string_type::npos) { | |
318 if(time_arg.zone_abbrev().empty()) { | |
319 // if zone_abbrev() returns an empty string, we want to | |
320 // erase posix_zone_string_format from format | |
321 boost::algorithm::erase_all(local_format, posix_zone_string_format); | |
322 } | |
323 else{ | |
324 boost::algorithm::replace_all(local_format, | |
325 posix_zone_string_format, | |
326 time_arg.zone_as_posix_string()); | |
327 } | |
328 } | |
329 if (local_format.find(zone_name_format) != string_type::npos) { | |
330 if(time_arg.zone_name().empty()) { | |
331 /* TODO: this'll probably create problems if a user places | |
332 * the zone_*_format flag in the format with a ptime. This | |
333 * code removes the flag from the default formats */ | |
334 | |
335 // if zone_name() returns an empty string, we want to | |
336 // erase zone_name_format & one preceeding space | |
337 std::basic_ostringstream<char_type> ss; | |
338 ss << ' ' << zone_name_format; | |
339 boost::algorithm::erase_all(local_format, ss.str()); | |
340 } | |
341 else{ | |
342 boost::algorithm::replace_all(local_format, | |
343 zone_name_format, | |
344 time_arg.zone_name()); | |
345 } | |
346 } | |
347 if (local_format.find(zone_abbrev_format) != string_type::npos) { | |
348 if(time_arg.zone_abbrev(false).empty()) { | |
349 /* TODO: this'll probably create problems if a user places | |
350 * the zone_*_format flag in the format with a ptime. This | |
351 * code removes the flag from the default formats */ | |
352 | |
353 // if zone_abbrev() returns an empty string, we want to | |
354 // erase zone_abbrev_format & one preceeding space | |
355 std::basic_ostringstream<char_type> ss; | |
356 ss << ' ' << zone_abbrev_format; | |
357 boost::algorithm::erase_all(local_format, ss.str()); | |
358 } | |
359 else{ | |
360 boost::algorithm::replace_all(local_format, | |
361 zone_abbrev_format, | |
362 time_arg.zone_abbrev(false)); | |
363 } | |
364 } | |
365 if (local_format.find(zone_iso_extended_format) != string_type::npos) { | |
366 if(time_arg.zone_name(true).empty()) { | |
367 /* TODO: this'll probably create problems if a user places | |
368 * the zone_*_format flag in the format with a ptime. This | |
369 * code removes the flag from the default formats */ | |
370 | |
371 // if zone_name() returns an empty string, we want to | |
372 // erase zone_iso_extended_format from format | |
373 boost::algorithm::erase_all(local_format, zone_iso_extended_format); | |
374 } | |
375 else{ | |
376 boost::algorithm::replace_all(local_format, | |
377 zone_iso_extended_format, | |
378 time_arg.zone_name(true)); | |
379 } | |
380 } | |
381 | |
382 if (local_format.find(zone_iso_format) != string_type::npos) { | |
383 if(time_arg.zone_abbrev(true).empty()) { | |
384 /* TODO: this'll probably create problems if a user places | |
385 * the zone_*_format flag in the format with a ptime. This | |
386 * code removes the flag from the default formats */ | |
387 | |
388 // if zone_abbrev() returns an empty string, we want to | |
389 // erase zone_iso_format from format | |
390 boost::algorithm::erase_all(local_format, zone_iso_format); | |
391 } | |
392 else{ | |
393 boost::algorithm::replace_all(local_format, | |
394 zone_iso_format, | |
395 time_arg.zone_abbrev(true)); | |
396 } | |
397 } | |
398 if (local_format.find(fractional_seconds_format) != string_type::npos) { | |
399 // replace %f with nnnnnnn | |
400 if (frac_str.empty()) { | |
401 frac_str = fractional_seconds_as_string(time_arg.time_of_day(), false); | |
402 } | |
403 boost::algorithm::replace_all(local_format, | |
404 fractional_seconds_format, | |
405 frac_str); | |
406 } | |
407 | |
408 if (local_format.find(fractional_seconds_or_none_format) != string_type::npos) { | |
409 // replace %F with nnnnnnn or nothing if fs == 0 | |
410 frac_str = | |
411 fractional_seconds_as_string(time_arg.time_of_day(), true); | |
412 if (frac_str.size()) { | |
413 char_type sep = std::use_facet<std::numpunct<char_type> >(ios_arg.getloc()).decimal_point(); | |
414 string_type replace_string; | |
415 replace_string += sep; | |
416 replace_string += frac_str; | |
417 boost::algorithm::replace_all(local_format, | |
418 fractional_seconds_or_none_format, | |
419 replace_string); | |
420 } | |
421 else { | |
422 boost::algorithm::erase_all(local_format, | |
423 fractional_seconds_or_none_format); | |
424 } | |
425 } | |
426 | |
427 return this->do_put_tm(next_arg, ios_arg, fill_arg, | |
428 to_tm(time_arg), local_format); | |
429 } | |
430 | |
431 //! put function for time_duration | |
432 OutItrT put(OutItrT next_arg, | |
433 std::ios_base& ios_arg, | |
434 char_type fill_arg, | |
435 const time_duration_type& time_dur_arg) const | |
436 { | |
437 if (time_dur_arg.is_special()) { | |
438 return this->do_put_special(next_arg, ios_arg, fill_arg, | |
439 time_dur_arg.get_rep().as_special()); | |
440 } | |
441 | |
442 string_type format(m_time_duration_format); | |
443 if (time_dur_arg.is_negative()) { | |
444 // replace %- with minus sign. Should we use the numpunct facet? | |
445 boost::algorithm::replace_all(format, | |
446 duration_sign_negative_only, | |
447 negative_sign); | |
448 // remove all the %+ in the string with '-' | |
449 boost::algorithm::replace_all(format, | |
450 duration_sign_always, | |
451 negative_sign); | |
452 } | |
453 else { //duration is positive | |
454 // remove all the %- combos from the string | |
455 boost::algorithm::erase_all(format, duration_sign_negative_only); | |
456 // remove all the %+ in the string with '+' | |
457 boost::algorithm::replace_all(format, | |
458 duration_sign_always, | |
459 positive_sign); | |
460 } | |
461 | |
462 // %T and %R have to be replaced here since they are not standard | |
463 boost::algorithm::replace_all(format, | |
464 boost::as_literal(formats_type::full_24_hour_time_format), | |
465 boost::as_literal(formats_type::full_24_hour_time_expanded_format)); | |
466 boost::algorithm::replace_all(format, | |
467 boost::as_literal(formats_type::short_24_hour_time_format), | |
468 boost::as_literal(formats_type::short_24_hour_time_expanded_format)); | |
469 | |
470 /* | |
471 * It is possible for a time duration to span more then 24 hours. | |
472 * Standard time_put::put is obliged to behave the same as strftime | |
473 * (See ISO 14882-2003 22.2.5.3.1 par. 1) and strftime's behavior is | |
474 * unspecified for the case when tm_hour field is outside 0-23 range | |
475 * (See ISO 9899-1999 7.23.3.5 par. 3). So we must output %H and %O | |
476 * here ourself. | |
477 */ | |
478 string_type hours_str; | |
479 if (format.find(unrestricted_hours_format) != string_type::npos) { | |
480 hours_str = hours_as_string(time_dur_arg); | |
481 boost::algorithm::replace_all(format, unrestricted_hours_format, hours_str); | |
482 } | |
483 // We still have to process restricted hours format specifier. In order to | |
484 // support parseability of durations in ISO format (%H%M%S), we'll have to | |
485 // restrict the stringified hours length to 2 characters. | |
486 if (format.find(hours_format) != string_type::npos) { | |
487 if (hours_str.empty()) | |
488 hours_str = hours_as_string(time_dur_arg); | |
489 BOOST_ASSERT(hours_str.length() <= 2); | |
490 boost::algorithm::replace_all(format, hours_format, hours_str); | |
491 } | |
492 | |
493 string_type frac_str; | |
494 if (format.find(seconds_with_fractional_seconds_format) != string_type::npos) { | |
495 // replace %s with %S.nnn | |
496 frac_str = | |
497 fractional_seconds_as_string(time_dur_arg, false); | |
498 char_type sep = std::use_facet<std::numpunct<char_type> >(ios_arg.getloc()).decimal_point(); | |
499 | |
500 string_type replace_string(seconds_format); | |
501 replace_string += sep; | |
502 replace_string += frac_str; | |
503 boost::algorithm::replace_all(format, | |
504 seconds_with_fractional_seconds_format, | |
505 replace_string); | |
506 } | |
507 if (format.find(fractional_seconds_format) != string_type::npos) { | |
508 // replace %f with nnnnnnn | |
509 if (!frac_str.size()) { | |
510 frac_str = fractional_seconds_as_string(time_dur_arg, false); | |
511 } | |
512 boost::algorithm::replace_all(format, | |
513 fractional_seconds_format, | |
514 frac_str); | |
515 } | |
516 | |
517 if (format.find(fractional_seconds_or_none_format) != string_type::npos) { | |
518 // replace %F with nnnnnnn or nothing if fs == 0 | |
519 frac_str = | |
520 fractional_seconds_as_string(time_dur_arg, true); | |
521 if (frac_str.size()) { | |
522 char_type sep = std::use_facet<std::numpunct<char_type> >(ios_arg.getloc()).decimal_point(); | |
523 string_type replace_string; | |
524 replace_string += sep; | |
525 replace_string += frac_str; | |
526 boost::algorithm::replace_all(format, | |
527 fractional_seconds_or_none_format, | |
528 replace_string); | |
529 } | |
530 else { | |
531 boost::algorithm::erase_all(format, | |
532 fractional_seconds_or_none_format); | |
533 } | |
534 } | |
535 | |
536 return this->do_put_tm(next_arg, ios_arg, fill_arg, | |
537 to_tm(time_dur_arg), format); | |
538 } | |
539 | |
540 OutItrT put(OutItrT next, std::ios_base& ios_arg, | |
541 char_type fill, const period_type& p) const | |
542 { | |
543 return this->m_period_formatter.put_period(next, ios_arg, fill,p,*this); | |
544 } | |
545 | |
546 | |
547 protected: | |
548 | |
549 static | |
550 string_type | |
551 fractional_seconds_as_string(const time_duration_type& time_arg, | |
552 bool null_when_zero) | |
553 { | |
554 typename time_duration_type::fractional_seconds_type frac_sec = | |
555 time_arg.fractional_seconds(); | |
556 | |
557 if (null_when_zero && (frac_sec == 0)) { | |
558 return string_type(); | |
559 } | |
560 | |
561 //make sure there is no sign | |
562 return integral_as_string( | |
563 date_time::absolute_value(frac_sec), | |
564 time_duration_type::num_fractional_digits()); | |
565 } | |
566 | |
567 static | |
568 string_type | |
569 hours_as_string(const time_duration_type& time_arg, int width = 2) | |
570 { | |
571 return integral_as_string(date_time::absolute_value(time_arg.hours()), width); | |
572 } | |
573 | |
574 template< typename IntT > | |
575 static | |
576 string_type | |
577 integral_as_string(IntT val, int width = 2) | |
578 { | |
579 std::basic_ostringstream<char_type> ss; | |
580 ss.imbue(std::locale::classic()); // don't want any formatting | |
581 ss << std::setw(width) | |
582 << std::setfill(static_cast<char_type>('0')); | |
583 #if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) | |
584 // JDG [7/6/02 VC++ compatibility] | |
585 char_type buff[34]; | |
586 ss << _i64toa(static_cast<boost::int64_t>(val), buff, 10); | |
587 #else | |
588 ss << val; | |
589 #endif | |
590 return ss.str(); | |
591 } | |
592 | |
593 private: | |
594 string_type m_time_duration_format; | |
595 | |
596 }; | |
597 | |
598 template <class time_type, class CharT, class OutItrT> | |
599 std::locale::id time_facet<time_type, CharT, OutItrT>::id; | |
600 | |
601 template <class time_type, class CharT, class OutItrT> | |
602 const typename time_facet<time_type, CharT, OutItrT>::char_type* | |
603 time_facet<time_type, CharT, OutItrT>::fractional_seconds_format = time_formats<CharT>::fractional_seconds_format; | |
604 | |
605 template <class time_type, class CharT, class OutItrT> | |
606 const typename time_facet<time_type, CharT, OutItrT>::char_type* | |
607 time_facet<time_type, CharT, OutItrT>::fractional_seconds_or_none_format = time_formats<CharT>::fractional_seconds_or_none_format; | |
608 | |
609 template <class time_type, class CharT, class OutItrT> | |
610 const typename time_facet<time_type, CharT, OutItrT>::char_type* | |
611 time_facet<time_type, CharT, OutItrT>::seconds_with_fractional_seconds_format = | |
612 time_formats<CharT>::seconds_with_fractional_seconds_format; | |
613 | |
614 | |
615 template <class time_type, class CharT, class OutItrT> | |
616 const typename time_facet<time_type, CharT, OutItrT>::char_type* | |
617 time_facet<time_type, CharT, OutItrT>::zone_name_format = time_formats<CharT>::zone_name_format; | |
618 | |
619 template <class time_type, class CharT, class OutItrT> | |
620 const typename time_facet<time_type, CharT, OutItrT>::char_type* | |
621 time_facet<time_type, CharT, OutItrT>::zone_abbrev_format = time_formats<CharT>::zone_abbrev_format; | |
622 | |
623 template <class time_type, class CharT, class OutItrT> | |
624 const typename time_facet<time_type, CharT, OutItrT>::char_type* | |
625 time_facet<time_type, CharT, OutItrT>::zone_iso_extended_format =time_formats<CharT>::zone_iso_extended_format; | |
626 | |
627 template <class time_type, class CharT, class OutItrT> | |
628 const typename time_facet<time_type, CharT, OutItrT>::char_type* | |
629 time_facet<time_type, CharT, OutItrT>::posix_zone_string_format =time_formats<CharT>::posix_zone_string_format; | |
630 | |
631 template <class time_type, class CharT, class OutItrT> | |
632 const typename time_facet<time_type, CharT, OutItrT>::char_type* | |
633 time_facet<time_type, CharT, OutItrT>::zone_iso_format = time_formats<CharT>::zone_iso_format; | |
634 | |
635 template <class time_type, class CharT, class OutItrT> | |
636 const typename time_facet<time_type, CharT, OutItrT>::char_type* | |
637 time_facet<time_type, CharT, OutItrT>::seconds_format = time_formats<CharT>::seconds_format; | |
638 | |
639 template <class time_type, class CharT, class OutItrT> | |
640 const typename time_facet<time_type, CharT, OutItrT>::char_type* | |
641 time_facet<time_type, CharT, OutItrT>::hours_format = time_formats<CharT>::hours_format; | |
642 | |
643 template <class time_type, class CharT, class OutItrT> | |
644 const typename time_facet<time_type, CharT, OutItrT>::char_type* | |
645 time_facet<time_type, CharT, OutItrT>::unrestricted_hours_format = time_formats<CharT>::unrestricted_hours_format; | |
646 | |
647 template <class time_type, class CharT, class OutItrT> | |
648 const typename time_facet<time_type, CharT, OutItrT>::char_type* | |
649 time_facet<time_type, CharT, OutItrT>::standard_format = time_formats<CharT>::standard_format; | |
650 | |
651 template <class time_type, class CharT, class OutItrT> | |
652 const typename time_facet<time_type, CharT, OutItrT>::char_type* | |
653 time_facet<time_type, CharT, OutItrT>::duration_seperator = time_formats<CharT>::duration_seperator; | |
654 | |
655 template <class time_type, class CharT, class OutItrT> | |
656 const typename time_facet<time_type, CharT, OutItrT>::char_type* | |
657 time_facet<time_type, CharT, OutItrT>::negative_sign = time_formats<CharT>::negative_sign; | |
658 | |
659 template <class time_type, class CharT, class OutItrT> | |
660 const typename time_facet<time_type, CharT, OutItrT>::char_type* | |
661 time_facet<time_type, CharT, OutItrT>::positive_sign = time_formats<CharT>::positive_sign; | |
662 | |
663 template <class time_type, class CharT, class OutItrT> | |
664 const typename time_facet<time_type, CharT, OutItrT>::char_type* | |
665 time_facet<time_type, CharT, OutItrT>::duration_sign_negative_only = time_formats<CharT>::duration_sign_negative_only; | |
666 | |
667 template <class time_type, class CharT, class OutItrT> | |
668 const typename time_facet<time_type, CharT, OutItrT>::char_type* | |
669 time_facet<time_type, CharT, OutItrT>::duration_sign_always = time_formats<CharT>::duration_sign_always; | |
670 | |
671 template <class time_type, class CharT, class OutItrT> | |
672 const typename time_facet<time_type,CharT, OutItrT>::char_type* | |
673 time_facet<time_type,CharT, OutItrT>::iso_time_format_specifier = time_formats<CharT>::iso_time_format_specifier; | |
674 | |
675 template <class time_type, class CharT, class OutItrT> | |
676 const typename time_facet<time_type, CharT, OutItrT>::char_type* | |
677 time_facet<time_type, CharT, OutItrT>::iso_time_format_extended_specifier = time_formats<CharT>::iso_time_format_extended_specifier; | |
678 | |
679 template <class time_type, class CharT, class OutItrT> | |
680 const typename time_facet<time_type, CharT, OutItrT>::char_type* | |
681 time_facet<time_type, CharT, OutItrT>::default_time_format = | |
682 time_formats<CharT>::default_time_format; | |
683 | |
684 template <class time_type, class CharT, class OutItrT> | |
685 const typename time_facet<time_type, CharT, OutItrT>::char_type* | |
686 time_facet<time_type, CharT, OutItrT>::default_time_duration_format = | |
687 time_formats<CharT>::default_time_duration_format; | |
688 | |
689 | |
690 //! Facet for format-based input. | |
691 /*! | |
692 */ | |
693 template <class time_type, | |
694 class CharT, | |
695 class InItrT = std::istreambuf_iterator<CharT, std::char_traits<CharT> > > | |
696 class time_input_facet : | |
697 public boost::date_time::date_input_facet<typename time_type::date_type , CharT, InItrT> { | |
698 public: | |
699 typedef typename time_type::date_type date_type; | |
700 typedef typename time_type::time_duration_type time_duration_type; | |
701 typedef typename time_duration_type::fractional_seconds_type fracional_seconds_type; | |
702 typedef boost::date_time::period<time_type,time_duration_type> period_type; | |
703 typedef boost::date_time::date_input_facet<typename time_type::date_type, CharT, InItrT> base_type; | |
704 typedef typename base_type::duration_type date_duration_type; | |
705 typedef typename base_type::year_type year_type; | |
706 typedef typename base_type::month_type month_type; | |
707 typedef typename base_type::day_type day_type; | |
708 typedef typename base_type::string_type string_type; | |
709 typedef typename string_type::const_iterator const_itr; | |
710 typedef typename base_type::char_type char_type; | |
711 typedef typename base_type::format_date_parser_type format_date_parser_type; | |
712 typedef typename base_type::period_parser_type period_parser_type; | |
713 typedef typename base_type::special_values_parser_type special_values_parser_type; | |
714 typedef typename base_type::date_gen_parser_type date_gen_parser_type; | |
715 typedef typename base_type::special_values_parser_type::match_results match_results; | |
716 | |
717 static const char_type* fractional_seconds_format; // f | |
718 static const char_type* fractional_seconds_or_none_format; // F | |
719 static const char_type* seconds_with_fractional_seconds_format; // s | |
720 static const char_type* seconds_format; // S | |
721 static const char_type* standard_format; // x X | |
722 static const char_type* zone_abbrev_format; // z | |
723 static const char_type* zone_name_format; // Z | |
724 static const char_type* zone_iso_format; // q | |
725 static const char_type* zone_iso_extended_format; // Q | |
726 static const char_type* duration_seperator; | |
727 static const char_type* iso_time_format_specifier; | |
728 static const char_type* iso_time_format_extended_specifier; | |
729 static const char_type* default_time_input_format; | |
730 static const char_type* default_time_duration_format; | |
731 static std::locale::id id; | |
732 | |
733 //! Constructor that takes a format string for a ptime | |
734 explicit time_input_facet(const string_type& format, ::size_t ref_arg = 0) | |
735 : base_type(format, ref_arg), | |
736 m_time_duration_format(default_time_duration_format) | |
737 { } | |
738 | |
739 explicit time_input_facet(const string_type& format, | |
740 const format_date_parser_type& date_parser, | |
741 const special_values_parser_type& sv_parser, | |
742 const period_parser_type& per_parser, | |
743 const date_gen_parser_type& date_gen_parser, | |
744 ::size_t ref_arg = 0) | |
745 : base_type(format, | |
746 date_parser, | |
747 sv_parser, | |
748 per_parser, | |
749 date_gen_parser, | |
750 ref_arg), | |
751 m_time_duration_format(default_time_duration_format) | |
752 {} | |
753 | |
754 //! sets default formats for ptime, local_date_time, and time_duration | |
755 explicit time_input_facet(::size_t ref_arg = 0) | |
756 : base_type(default_time_input_format, ref_arg), | |
757 m_time_duration_format(default_time_duration_format) | |
758 { } | |
759 | |
760 //! Set the format for time_duration | |
761 void time_duration_format(const char_type* const format) { | |
762 m_time_duration_format = format; | |
763 } | |
764 virtual void set_iso_format() | |
765 { | |
766 this->m_format = iso_time_format_specifier; | |
767 } | |
768 virtual void set_iso_extended_format() | |
769 { | |
770 this->m_format = iso_time_format_extended_specifier; | |
771 } | |
772 | |
773 InItrT get(InItrT& sitr, | |
774 InItrT& stream_end, | |
775 std::ios_base& ios_arg, | |
776 period_type& p) const | |
777 { | |
778 p = this->m_period_parser.get_period(sitr, | |
779 stream_end, | |
780 ios_arg, | |
781 p, | |
782 time_duration_type::unit(), | |
783 *this); | |
784 return sitr; | |
785 } | |
786 | |
787 //default ptime format is YYYY-Mon-DD HH:MM:SS[.fff...][ zzz] | |
788 //default time_duration format is %H:%M:%S%F HH:MM:SS[.fff...] | |
789 | |
790 InItrT get(InItrT& sitr, | |
791 InItrT& stream_end, | |
792 std::ios_base& ios_arg, | |
793 time_duration_type& td) const | |
794 { | |
795 // skip leading whitespace | |
796 while((sitr != stream_end) && std::isspace(*sitr)) { ++sitr; } | |
797 | |
798 bool use_current_char = false; | |
799 | |
800 // num_get will consume the +/-, we may need a copy if special_value | |
801 char_type c = '\0'; | |
802 if((sitr != stream_end) && (*sitr == '-' || *sitr == '+')) { | |
803 c = *sitr; | |
804 } | |
805 | |
806 typedef typename time_duration_type::hour_type hour_type; | |
807 typedef typename time_duration_type::min_type min_type; | |
808 typedef typename time_duration_type::sec_type sec_type; | |
809 | |
810 hour_type hour = 0; | |
811 min_type min = 0; | |
812 sec_type sec = 0; | |
813 typename time_duration_type::fractional_seconds_type frac(0); | |
814 | |
815 typedef std::num_get<CharT, InItrT> num_get; | |
816 if(!std::has_facet<num_get>(ios_arg.getloc())) { | |
817 num_get* ng = new num_get(); | |
818 std::locale loc = std::locale(ios_arg.getloc(), ng); | |
819 ios_arg.imbue(loc); | |
820 } | |
821 | |
822 const_itr itr(m_time_duration_format.begin()); | |
823 while (itr != m_time_duration_format.end() && (sitr != stream_end)) { | |
824 if (*itr == '%') { | |
825 if (++itr == m_time_duration_format.end()) break; | |
826 if (*itr != '%') { | |
827 switch(*itr) { | |
828 case 'O': | |
829 { | |
830 // A period may span more than 24 hours. In that case the format | |
831 // string should be composed with the unrestricted hours specifier. | |
832 hour = var_string_to_int<hour_type, CharT>(sitr, stream_end, | |
833 std::numeric_limits<hour_type>::digits10 + 1); | |
834 if(hour == -1){ | |
835 return check_special_value(sitr, stream_end, td, c); | |
836 } | |
837 break; | |
838 } | |
839 case 'H': | |
840 { | |
841 match_results mr; | |
842 hour = fixed_string_to_int<hour_type, CharT>(sitr, stream_end, mr, 2); | |
843 if(hour == -1){ | |
844 return check_special_value(sitr, stream_end, td, c); | |
845 } | |
846 break; | |
847 } | |
848 case 'M': | |
849 { | |
850 match_results mr; | |
851 min = fixed_string_to_int<min_type, CharT>(sitr, stream_end, mr, 2); | |
852 if(min == -1){ | |
853 return check_special_value(sitr, stream_end, td, c); | |
854 } | |
855 break; | |
856 } | |
857 case 's': | |
858 case 'S': | |
859 { | |
860 match_results mr; | |
861 sec = fixed_string_to_int<sec_type, CharT>(sitr, stream_end, mr, 2); | |
862 if(sec == -1){ | |
863 return check_special_value(sitr, stream_end, td, c); | |
864 } | |
865 if (*itr == 'S') | |
866 break; | |
867 // %s is the same as %S%f so we drop through into %f | |
868 } | |
869 case 'f': | |
870 { | |
871 // check for decimal, check special_values if missing | |
872 if(*sitr == '.') { | |
873 ++sitr; | |
874 parse_frac_type(sitr, stream_end, frac); | |
875 // sitr will point to next expected char after this parsing | |
876 // is complete so no need to advance it | |
877 use_current_char = true; | |
878 } | |
879 else { | |
880 return check_special_value(sitr, stream_end, td, c); | |
881 } | |
882 break; | |
883 } | |
884 case 'F': | |
885 { | |
886 // check for decimal, skip if missing | |
887 if(*sitr == '.') { | |
888 ++sitr; | |
889 parse_frac_type(sitr, stream_end, frac); | |
890 // sitr will point to next expected char after this parsing | |
891 // is complete so no need to advance it | |
892 use_current_char = true; | |
893 } | |
894 else { | |
895 // nothing was parsed so we don't want to advance sitr | |
896 use_current_char = true; | |
897 } | |
898 break; | |
899 } | |
900 default: | |
901 {} // ignore what we don't understand? | |
902 }// switch | |
903 } | |
904 else { // itr == '%', second consecutive | |
905 ++sitr; | |
906 } | |
907 | |
908 ++itr; //advance past format specifier | |
909 } | |
910 else { //skip past chars in format and in buffer | |
911 ++itr; | |
912 // set use_current_char when sitr is already | |
913 // pointing at the next character to process | |
914 if (use_current_char) { | |
915 use_current_char = false; | |
916 } | |
917 else { | |
918 ++sitr; | |
919 } | |
920 } | |
921 } | |
922 | |
923 td = time_duration_type(hour, min, sec, frac); | |
924 return sitr; | |
925 } | |
926 | |
927 | |
928 //! Parses a time object from the input stream | |
929 InItrT get(InItrT& sitr, | |
930 InItrT& stream_end, | |
931 std::ios_base& ios_arg, | |
932 time_type& t) const | |
933 { | |
934 string_type tz_str; | |
935 return get(sitr, stream_end, ios_arg, t, tz_str, false); | |
936 } | |
937 //! Expects a time_zone in the input stream | |
938 InItrT get_local_time(InItrT& sitr, | |
939 InItrT& stream_end, | |
940 std::ios_base& ios_arg, | |
941 time_type& t, | |
942 string_type& tz_str) const | |
943 { | |
944 return get(sitr, stream_end, ios_arg, t, tz_str, true); | |
945 } | |
946 | |
947 protected: | |
948 | |
949 InItrT get(InItrT& sitr, | |
950 InItrT& stream_end, | |
951 std::ios_base& ios_arg, | |
952 time_type& t, | |
953 string_type& tz_str, | |
954 bool time_is_local) const | |
955 { | |
956 // skip leading whitespace | |
957 while((sitr != stream_end) && std::isspace(*sitr)) { ++sitr; } | |
958 | |
959 bool use_current_char = false; | |
960 bool use_current_format_char = false; // used whith two character flags | |
961 | |
962 // num_get will consume the +/-, we may need a copy if special_value | |
963 char_type c = '\0'; | |
964 if((sitr != stream_end) && (*sitr == '-' || *sitr == '+')) { | |
965 c = *sitr; | |
966 } | |
967 | |
968 typedef typename time_duration_type::hour_type hour_type; | |
969 typedef typename time_duration_type::min_type min_type; | |
970 typedef typename time_duration_type::sec_type sec_type; | |
971 | |
972 // time elements | |
973 hour_type hour = 0; | |
974 min_type min = 0; | |
975 sec_type sec = 0; | |
976 typename time_duration_type::fractional_seconds_type frac(0); | |
977 // date elements | |
978 short day_of_year(0); | |
979 /* Initialized the following to their minimum values. These intermediate | |
980 * objects are used so we get specific exceptions when part of the input | |
981 * is unparsable. | |
982 * Ex: "205-Jan-15" will throw a bad_year, "2005-Jsn-15"- bad_month, etc.*/ | |
983 year_type t_year(1400); | |
984 month_type t_month(1); | |
985 day_type t_day(1); | |
986 | |
987 typedef std::num_get<CharT, InItrT> num_get; | |
988 if(!std::has_facet<num_get>(ios_arg.getloc())) { | |
989 num_get* ng = new num_get(); | |
990 std::locale loc = std::locale(ios_arg.getloc(), ng); | |
991 ios_arg.imbue(loc); | |
992 } | |
993 | |
994 const_itr itr(this->m_format.begin()); | |
995 while (itr != this->m_format.end() && (sitr != stream_end)) { | |
996 if (*itr == '%') { | |
997 if (++itr == this->m_format.end()) break; | |
998 if (*itr != '%') { | |
999 // the cases are grouped by date & time flags - not alphabetical order | |
1000 switch(*itr) { | |
1001 // date flags | |
1002 case 'Y': | |
1003 case 'y': | |
1004 { | |
1005 char_type cs[3] = { '%', *itr }; | |
1006 string_type s(cs); | |
1007 match_results mr; | |
1008 try { | |
1009 t_year = this->m_parser.parse_year(sitr, stream_end, s, mr); | |
1010 } | |
1011 catch(std::out_of_range&) { // base class for bad_year exception | |
1012 if(this->m_sv_parser.match(sitr, stream_end, mr)) { | |
1013 t = time_type(static_cast<special_values>(mr.current_match)); | |
1014 return sitr; | |
1015 } | |
1016 else { | |
1017 throw; // rethrow bad_year | |
1018 } | |
1019 } | |
1020 break; | |
1021 } | |
1022 case 'B': | |
1023 case 'b': | |
1024 case 'm': | |
1025 { | |
1026 char_type cs[3] = { '%', *itr }; | |
1027 string_type s(cs); | |
1028 match_results mr; | |
1029 try { | |
1030 t_month = this->m_parser.parse_month(sitr, stream_end, s, mr); | |
1031 } | |
1032 catch(std::out_of_range&) { // base class for bad_month exception | |
1033 if(this->m_sv_parser.match(sitr, stream_end, mr)) { | |
1034 t = time_type(static_cast<special_values>(mr.current_match)); | |
1035 return sitr; | |
1036 } | |
1037 else { | |
1038 throw; // rethrow bad_month | |
1039 } | |
1040 } | |
1041 // did m_parser already advance sitr to next char? | |
1042 if(mr.has_remaining()) { | |
1043 use_current_char = true; | |
1044 } | |
1045 break; | |
1046 } | |
1047 case 'a': | |
1048 case 'A': | |
1049 case 'w': | |
1050 { | |
1051 // weekday is not used in construction but we need to get it out of the stream | |
1052 char_type cs[3] = { '%', *itr }; | |
1053 string_type s(cs); | |
1054 match_results mr; | |
1055 typename date_type::day_of_week_type wd(0); | |
1056 try { | |
1057 wd = this->m_parser.parse_weekday(sitr, stream_end, s, mr); | |
1058 } | |
1059 catch(std::out_of_range&) { // base class for bad_weekday exception | |
1060 if(this->m_sv_parser.match(sitr, stream_end, mr)) { | |
1061 t = time_type(static_cast<special_values>(mr.current_match)); | |
1062 return sitr; | |
1063 } | |
1064 else { | |
1065 throw; // rethrow bad_weekday | |
1066 } | |
1067 } | |
1068 // did m_parser already advance sitr to next char? | |
1069 if(mr.has_remaining()) { | |
1070 use_current_char = true; | |
1071 } | |
1072 break; | |
1073 } | |
1074 case 'j': | |
1075 { | |
1076 // code that gets julian day (from format_date_parser) | |
1077 match_results mr; | |
1078 day_of_year = fixed_string_to_int<unsigned short, CharT>(sitr, stream_end, mr, 3); | |
1079 if(day_of_year == -1) { | |
1080 if(this->m_sv_parser.match(sitr, stream_end, mr)) { | |
1081 t = time_type(static_cast<special_values>(mr.current_match)); | |
1082 return sitr; | |
1083 } | |
1084 } | |
1085 // these next two lines are so we get an exception with bad input | |
1086 typedef typename time_type::date_type::day_of_year_type day_of_year_type; | |
1087 day_of_year_type t_day_of_year(day_of_year); | |
1088 break; | |
1089 } | |
1090 case 'd': | |
1091 { | |
1092 try { | |
1093 t_day = this->m_parser.parse_day_of_month(sitr, stream_end); | |
1094 } | |
1095 catch(std::out_of_range&) { // base class for exception bad_day_of_month | |
1096 match_results mr; | |
1097 if(this->m_sv_parser.match(sitr, stream_end, mr)) { | |
1098 t = time_type(static_cast<special_values>(mr.current_match)); | |
1099 return sitr; | |
1100 } | |
1101 else { | |
1102 throw; // rethrow bad_day_of_month | |
1103 } | |
1104 } | |
1105 break; | |
1106 } | |
1107 // time flags | |
1108 case 'H': | |
1109 { | |
1110 match_results mr; | |
1111 hour = fixed_string_to_int<hour_type, CharT>(sitr, stream_end, mr, 2); | |
1112 if(hour == -1){ | |
1113 return check_special_value(sitr, stream_end, t, c); | |
1114 } | |
1115 break; | |
1116 } | |
1117 case 'M': | |
1118 { | |
1119 match_results mr; | |
1120 min = fixed_string_to_int<min_type, CharT>(sitr, stream_end, mr, 2); | |
1121 if(min == -1){ | |
1122 return check_special_value(sitr, stream_end, t, c); | |
1123 } | |
1124 break; | |
1125 } | |
1126 case 's': | |
1127 case 'S': | |
1128 { | |
1129 match_results mr; | |
1130 sec = fixed_string_to_int<sec_type, CharT>(sitr, stream_end, mr, 2); | |
1131 if(sec == -1){ | |
1132 return check_special_value(sitr, stream_end, t, c); | |
1133 } | |
1134 if (*itr == 'S') | |
1135 break; | |
1136 // %s is the same as %S%f so we drop through into %f | |
1137 } | |
1138 case 'f': | |
1139 { | |
1140 // check for decimal, check SV if missing | |
1141 if(*sitr == '.') { | |
1142 ++sitr; | |
1143 parse_frac_type(sitr, stream_end, frac); | |
1144 // sitr will point to next expected char after this parsing | |
1145 // is complete so no need to advance it | |
1146 use_current_char = true; | |
1147 } | |
1148 else { | |
1149 return check_special_value(sitr, stream_end, t, c); | |
1150 } | |
1151 break; | |
1152 } | |
1153 case 'F': | |
1154 { | |
1155 // check for decimal, skip if missing | |
1156 if(*sitr == '.') { | |
1157 ++sitr; | |
1158 parse_frac_type(sitr, stream_end, frac); | |
1159 // sitr will point to next expected char after this parsing | |
1160 // is complete so no need to advance it | |
1161 use_current_char = true; | |
1162 } | |
1163 else { | |
1164 // nothing was parsed so we don't want to advance sitr | |
1165 use_current_char = true; | |
1166 } | |
1167 break; | |
1168 } | |
1169 // time_zone flags | |
1170 //case 'q': | |
1171 //case 'Q': | |
1172 //case 'z': | |
1173 case 'Z': | |
1174 { | |
1175 if(time_is_local) { // skip if 't' is a ptime | |
1176 ++itr; | |
1177 if(*itr == 'P') { | |
1178 // skip leading whitespace | |
1179 while((sitr != stream_end) && std::isspace(*sitr)) { ++sitr; } | |
1180 // parse zone | |
1181 while((sitr != stream_end) && (!std::isspace(*sitr))) { | |
1182 tz_str += *sitr; | |
1183 ++sitr; | |
1184 } | |
1185 } | |
1186 else { | |
1187 use_current_format_char = true; | |
1188 } | |
1189 | |
1190 } | |
1191 else { | |
1192 // nothing was parsed so we don't want to advance sitr | |
1193 use_current_char = true; | |
1194 } | |
1195 | |
1196 break; | |
1197 } | |
1198 default: | |
1199 {} // ignore what we don't understand? | |
1200 }// switch | |
1201 } | |
1202 else { // itr == '%', second consecutive | |
1203 ++sitr; | |
1204 } | |
1205 | |
1206 if(use_current_format_char) { | |
1207 use_current_format_char = false; | |
1208 } | |
1209 else { | |
1210 ++itr; //advance past format specifier | |
1211 } | |
1212 | |
1213 } | |
1214 else { //skip past chars in format and in buffer | |
1215 ++itr; | |
1216 // set use_current_char when sitr is already | |
1217 // pointing at the next character to process | |
1218 if (use_current_char) { | |
1219 use_current_char = false; | |
1220 } | |
1221 else { | |
1222 ++sitr; | |
1223 } | |
1224 } | |
1225 } | |
1226 | |
1227 date_type d(not_a_date_time); | |
1228 if (day_of_year > 0) { | |
1229 d = date_type(static_cast<unsigned short>(t_year-1),12,31) + date_duration_type(day_of_year); | |
1230 } | |
1231 else { | |
1232 d = date_type(t_year, t_month, t_day); | |
1233 } | |
1234 | |
1235 time_duration_type td(hour, min, sec, frac); | |
1236 t = time_type(d, td); | |
1237 return sitr; | |
1238 } | |
1239 | |
1240 //! Helper function to check for special_value | |
1241 /*! First character may have been consumed during original parse | |
1242 * attempt. Parameter 'c' should be a copy of that character. | |
1243 * Throws ios_base::failure if parse fails. */ | |
1244 template<class temporal_type> | |
1245 inline | |
1246 InItrT check_special_value(InItrT& sitr,InItrT& stream_end, temporal_type& tt, char_type c='\0') const | |
1247 { | |
1248 match_results mr; | |
1249 if((c == '-' || c == '+') && (*sitr != c)) { // was the first character consumed? | |
1250 mr.cache += c; | |
1251 } | |
1252 this->m_sv_parser.match(sitr, stream_end, mr); | |
1253 if(mr.current_match == match_results::PARSE_ERROR) { | |
1254 std::string tmp = convert_string_type<char_type, char>(mr.cache); | |
1255 boost::throw_exception(std::ios_base::failure("Parse failed. No match found for '" + tmp + "'")); | |
1256 BOOST_DATE_TIME_UNREACHABLE_EXPRESSION(return sitr); // should never reach | |
1257 } | |
1258 tt = temporal_type(static_cast<special_values>(mr.current_match)); | |
1259 return sitr; | |
1260 } | |
1261 | |
1262 //! Helper function for parsing a fractional second type from the stream | |
1263 void parse_frac_type(InItrT& sitr, | |
1264 InItrT& stream_end, | |
1265 fracional_seconds_type& frac) const | |
1266 { | |
1267 string_type cache; | |
1268 while((sitr != stream_end) && std::isdigit(*sitr)) { | |
1269 cache += *sitr; | |
1270 ++sitr; | |
1271 } | |
1272 if(cache.size() > 0) { | |
1273 unsigned short precision = time_duration_type::num_fractional_digits(); | |
1274 // input may be only the first few decimal places | |
1275 if(cache.size() < precision) { | |
1276 frac = lexical_cast<fracional_seconds_type>(cache); | |
1277 frac = decimal_adjust(frac, static_cast<unsigned short>(precision - cache.size())); | |
1278 } | |
1279 else { | |
1280 // if input has too many decimal places, drop excess digits | |
1281 frac = lexical_cast<fracional_seconds_type>(cache.substr(0, precision)); | |
1282 } | |
1283 } | |
1284 } | |
1285 | |
1286 private: | |
1287 string_type m_time_duration_format; | |
1288 | |
1289 //! Helper function to adjust trailing zeros when parsing fractional digits | |
1290 template<class int_type> | |
1291 inline | |
1292 int_type decimal_adjust(int_type val, const unsigned short places) const | |
1293 { | |
1294 unsigned long factor = 1; | |
1295 for(int i = 0; i < places; ++i){ | |
1296 factor *= 10; // shift decimal to the right | |
1297 } | |
1298 return val * factor; | |
1299 } | |
1300 | |
1301 }; | |
1302 | |
1303 template <class time_type, class CharT, class InItrT> | |
1304 std::locale::id time_input_facet<time_type, CharT, InItrT>::id; | |
1305 | |
1306 template <class time_type, class CharT, class InItrT> | |
1307 const typename time_input_facet<time_type, CharT, InItrT>::char_type* | |
1308 time_input_facet<time_type, CharT, InItrT>::fractional_seconds_format = time_formats<CharT>::fractional_seconds_format; | |
1309 | |
1310 template <class time_type, class CharT, class InItrT> | |
1311 const typename time_input_facet<time_type, CharT, InItrT>::char_type* | |
1312 time_input_facet<time_type, CharT, InItrT>::fractional_seconds_or_none_format = time_formats<CharT>::fractional_seconds_or_none_format; | |
1313 | |
1314 template <class time_type, class CharT, class InItrT> | |
1315 const typename time_input_facet<time_type, CharT, InItrT>::char_type* | |
1316 time_input_facet<time_type, CharT, InItrT>::seconds_with_fractional_seconds_format = time_formats<CharT>::seconds_with_fractional_seconds_format; | |
1317 | |
1318 template <class time_type, class CharT, class InItrT> | |
1319 const typename time_input_facet<time_type, CharT, InItrT>::char_type* | |
1320 time_input_facet<time_type, CharT, InItrT>::seconds_format = time_formats<CharT>::seconds_format; | |
1321 | |
1322 template <class time_type, class CharT, class InItrT> | |
1323 const typename time_input_facet<time_type, CharT, InItrT>::char_type* | |
1324 time_input_facet<time_type, CharT, InItrT>::standard_format = time_formats<CharT>::standard_format; | |
1325 | |
1326 template <class time_type, class CharT, class InItrT> | |
1327 const typename time_input_facet<time_type, CharT, InItrT>::char_type* | |
1328 time_input_facet<time_type, CharT, InItrT>::zone_abbrev_format = time_formats<CharT>::zone_abbrev_format; | |
1329 | |
1330 template <class time_type, class CharT, class InItrT> | |
1331 const typename time_input_facet<time_type, CharT, InItrT>::char_type* | |
1332 time_input_facet<time_type, CharT, InItrT>::zone_name_format = time_formats<CharT>::zone_name_format; | |
1333 | |
1334 template <class time_type, class CharT, class InItrT> | |
1335 const typename time_input_facet<time_type, CharT, InItrT>::char_type* | |
1336 time_input_facet<time_type, CharT, InItrT>::zone_iso_format = time_formats<CharT>::zone_iso_format; | |
1337 | |
1338 template <class time_type, class CharT, class InItrT> | |
1339 const typename time_input_facet<time_type, CharT, InItrT>::char_type* | |
1340 time_input_facet<time_type, CharT, InItrT>::zone_iso_extended_format = time_formats<CharT>::zone_iso_extended_format; | |
1341 | |
1342 template <class time_type, class CharT, class InItrT> | |
1343 const typename time_input_facet<time_type, CharT, InItrT>::char_type* | |
1344 time_input_facet<time_type, CharT, InItrT>::duration_seperator = time_formats<CharT>::duration_seperator; | |
1345 | |
1346 template <class time_type, class CharT, class InItrT> | |
1347 const typename time_input_facet<time_type, CharT, InItrT>::char_type* | |
1348 time_input_facet<time_type, CharT, InItrT>::iso_time_format_specifier = time_formats<CharT>::iso_time_format_specifier; | |
1349 | |
1350 template <class time_type, class CharT, class InItrT> | |
1351 const typename time_input_facet<time_type, CharT, InItrT>::char_type* | |
1352 time_input_facet<time_type, CharT, InItrT>::iso_time_format_extended_specifier = time_formats<CharT>::iso_time_format_extended_specifier; | |
1353 | |
1354 template <class time_type, class CharT, class InItrT> | |
1355 const typename time_input_facet<time_type, CharT, InItrT>::char_type* | |
1356 time_input_facet<time_type, CharT, InItrT>::default_time_input_format = time_formats<CharT>::default_time_input_format; | |
1357 | |
1358 template <class time_type, class CharT, class InItrT> | |
1359 const typename time_input_facet<time_type, CharT, InItrT>::char_type* | |
1360 time_input_facet<time_type, CharT, InItrT>::default_time_duration_format = time_formats<CharT>::default_time_duration_format; | |
1361 | |
1362 | |
1363 } } // namespaces | |
1364 | |
1365 | |
1366 #endif | |
1367 |