]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/date_time/time_facet.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / date_time / time_facet.hpp
CommitLineData
7c673cae
FG
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$
11 */
12
13#include <cctype>
20effc67
TL
14#include <exception>
15#include <iomanip>
16#include <iterator> // i/ostreambuf_iterator
7c673cae
FG
17#include <locale>
18#include <limits>
7c673cae 19#include <sstream>
20effc67 20#include <string>
7c673cae
FG
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
33namespace boost {
34namespace 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> > >
b32b8144 203 class BOOST_SYMBOL_VISIBLE time_facet :
7c673cae
FG
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
20effc67 272 void set_iso_format() BOOST_OVERRIDE
7c673cae
FG
273 {
274 this->m_format = iso_time_format_specifier;
275 }
20effc67 276 void set_iso_extended_format() BOOST_OVERRIDE
7c673cae
FG
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);
20effc67 412 if (!frac_str.empty()) {
7c673cae
FG
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> > >
b32b8144 696 class BOOST_SYMBOL_VISIBLE time_input_facet :
7c673cae
FG
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 }
11fdf7f2 869 /* Falls through. */
7c673cae
FG
870 case 'f':
871 {
872 // check for decimal, check special_values if missing
873 if(*sitr == '.') {
874 ++sitr;
875 parse_frac_type(sitr, stream_end, frac);
876 // sitr will point to next expected char after this parsing
877 // is complete so no need to advance it
878 use_current_char = true;
879 }
880 else {
881 return check_special_value(sitr, stream_end, td, c);
882 }
883 break;
884 }
885 case 'F':
886 {
887 // check for decimal, skip if missing
888 if(*sitr == '.') {
889 ++sitr;
890 parse_frac_type(sitr, stream_end, frac);
891 // sitr will point to next expected char after this parsing
892 // is complete so no need to advance it
893 use_current_char = true;
894 }
895 else {
896 // nothing was parsed so we don't want to advance sitr
897 use_current_char = true;
898 }
899 break;
900 }
901 default:
902 {} // ignore what we don't understand?
903 }// switch
904 }
905 else { // itr == '%', second consecutive
906 ++sitr;
907 }
908
909 ++itr; //advance past format specifier
910 }
911 else { //skip past chars in format and in buffer
912 ++itr;
913 // set use_current_char when sitr is already
914 // pointing at the next character to process
915 if (use_current_char) {
916 use_current_char = false;
917 }
918 else {
919 ++sitr;
920 }
921 }
922 }
923
924 td = time_duration_type(hour, min, sec, frac);
925 return sitr;
926 }
927
928
929 //! Parses a time object from the input stream
930 InItrT get(InItrT& sitr,
931 InItrT& stream_end,
932 std::ios_base& ios_arg,
933 time_type& t) const
934 {
935 string_type tz_str;
936 return get(sitr, stream_end, ios_arg, t, tz_str, false);
937 }
938 //! Expects a time_zone in the input stream
939 InItrT get_local_time(InItrT& sitr,
940 InItrT& stream_end,
941 std::ios_base& ios_arg,
942 time_type& t,
943 string_type& tz_str) const
944 {
945 return get(sitr, stream_end, ios_arg, t, tz_str, true);
946 }
947
948 protected:
949
950 InItrT get(InItrT& sitr,
951 InItrT& stream_end,
952 std::ios_base& ios_arg,
953 time_type& t,
954 string_type& tz_str,
955 bool time_is_local) const
956 {
957 // skip leading whitespace
958 while((sitr != stream_end) && std::isspace(*sitr)) { ++sitr; }
959
960 bool use_current_char = false;
20effc67 961 bool use_current_format_char = false; // used with two character flags
7c673cae
FG
962
963 // num_get will consume the +/-, we may need a copy if special_value
964 char_type c = '\0';
965 if((sitr != stream_end) && (*sitr == '-' || *sitr == '+')) {
966 c = *sitr;
967 }
968
969 typedef typename time_duration_type::hour_type hour_type;
970 typedef typename time_duration_type::min_type min_type;
971 typedef typename time_duration_type::sec_type sec_type;
972
973 // time elements
974 hour_type hour = 0;
975 min_type min = 0;
976 sec_type sec = 0;
977 typename time_duration_type::fractional_seconds_type frac(0);
978 // date elements
979 short day_of_year(0);
980 /* Initialized the following to their minimum values. These intermediate
981 * objects are used so we get specific exceptions when part of the input
982 * is unparsable.
983 * Ex: "205-Jan-15" will throw a bad_year, "2005-Jsn-15"- bad_month, etc.*/
984 year_type t_year(1400);
985 month_type t_month(1);
986 day_type t_day(1);
987
988 typedef std::num_get<CharT, InItrT> num_get;
989 if(!std::has_facet<num_get>(ios_arg.getloc())) {
990 num_get* ng = new num_get();
991 std::locale loc = std::locale(ios_arg.getloc(), ng);
992 ios_arg.imbue(loc);
993 }
994
995 const_itr itr(this->m_format.begin());
996 while (itr != this->m_format.end() && (sitr != stream_end)) {
997 if (*itr == '%') {
998 if (++itr == this->m_format.end()) break;
999 if (*itr != '%') {
1000 // the cases are grouped by date & time flags - not alphabetical order
1001 switch(*itr) {
1002 // date flags
1003 case 'Y':
1004 case 'y':
1005 {
1006 char_type cs[3] = { '%', *itr };
1007 string_type s(cs);
1008 match_results mr;
1009 try {
1010 t_year = this->m_parser.parse_year(sitr, stream_end, s, mr);
1011 }
1012 catch(std::out_of_range&) { // base class for bad_year exception
1013 if(this->m_sv_parser.match(sitr, stream_end, mr)) {
1014 t = time_type(static_cast<special_values>(mr.current_match));
1015 return sitr;
1016 }
1017 else {
1018 throw; // rethrow bad_year
1019 }
1020 }
1021 break;
1022 }
1023 case 'B':
1024 case 'b':
1025 case 'm':
1026 {
1027 char_type cs[3] = { '%', *itr };
1028 string_type s(cs);
1029 match_results mr;
1030 try {
1031 t_month = this->m_parser.parse_month(sitr, stream_end, s, mr);
1032 }
1033 catch(std::out_of_range&) { // base class for bad_month exception
1034 if(this->m_sv_parser.match(sitr, stream_end, mr)) {
1035 t = time_type(static_cast<special_values>(mr.current_match));
1036 return sitr;
1037 }
1038 else {
1039 throw; // rethrow bad_month
1040 }
1041 }
1042 // did m_parser already advance sitr to next char?
1043 if(mr.has_remaining()) {
1044 use_current_char = true;
1045 }
1046 break;
1047 }
1048 case 'a':
1049 case 'A':
1050 case 'w':
1051 {
1052 // weekday is not used in construction but we need to get it out of the stream
1053 char_type cs[3] = { '%', *itr };
1054 string_type s(cs);
1055 match_results mr;
1056 typename date_type::day_of_week_type wd(0);
1057 try {
1058 wd = this->m_parser.parse_weekday(sitr, stream_end, s, mr);
1059 }
1060 catch(std::out_of_range&) { // base class for bad_weekday exception
1061 if(this->m_sv_parser.match(sitr, stream_end, mr)) {
1062 t = time_type(static_cast<special_values>(mr.current_match));
1063 return sitr;
1064 }
1065 else {
1066 throw; // rethrow bad_weekday
1067 }
1068 }
1069 // did m_parser already advance sitr to next char?
1070 if(mr.has_remaining()) {
1071 use_current_char = true;
1072 }
1073 break;
1074 }
1075 case 'j':
1076 {
1077 // code that gets julian day (from format_date_parser)
1078 match_results mr;
1079 day_of_year = fixed_string_to_int<unsigned short, CharT>(sitr, stream_end, mr, 3);
1080 if(day_of_year == -1) {
1081 if(this->m_sv_parser.match(sitr, stream_end, mr)) {
1082 t = time_type(static_cast<special_values>(mr.current_match));
1083 return sitr;
1084 }
1085 }
1086 // these next two lines are so we get an exception with bad input
1087 typedef typename time_type::date_type::day_of_year_type day_of_year_type;
1088 day_of_year_type t_day_of_year(day_of_year);
1089 break;
1090 }
1091 case 'd':
11fdf7f2 1092 case 'e':
7c673cae
FG
1093 {
1094 try {
11fdf7f2
TL
1095 t_day = (*itr == 'd') ?
1096 this->m_parser.parse_day_of_month(sitr, stream_end) :
1097 this->m_parser.parse_var_day_of_month(sitr, stream_end);
7c673cae
FG
1098 }
1099 catch(std::out_of_range&) { // base class for exception bad_day_of_month
1100 match_results mr;
1101 if(this->m_sv_parser.match(sitr, stream_end, mr)) {
1102 t = time_type(static_cast<special_values>(mr.current_match));
1103 return sitr;
1104 }
1105 else {
1106 throw; // rethrow bad_day_of_month
1107 }
1108 }
1109 break;
1110 }
1111 // time flags
1112 case 'H':
1113 {
1114 match_results mr;
1115 hour = fixed_string_to_int<hour_type, CharT>(sitr, stream_end, mr, 2);
1116 if(hour == -1){
1117 return check_special_value(sitr, stream_end, t, c);
1118 }
1119 break;
1120 }
1121 case 'M':
1122 {
1123 match_results mr;
1124 min = fixed_string_to_int<min_type, CharT>(sitr, stream_end, mr, 2);
1125 if(min == -1){
1126 return check_special_value(sitr, stream_end, t, c);
1127 }
1128 break;
1129 }
1130 case 's':
1131 case 'S':
1132 {
1133 match_results mr;
1134 sec = fixed_string_to_int<sec_type, CharT>(sitr, stream_end, mr, 2);
1135 if(sec == -1){
1136 return check_special_value(sitr, stream_end, t, c);
1137 }
1138 if (*itr == 'S' || sitr == stream_end)
1139 break;
1140 // %s is the same as %S%f so we drop through into %f if we are
1141 // not at the end of the stream
1142 }
11fdf7f2 1143 /* Falls through. */
7c673cae
FG
1144 case 'f':
1145 {
1146 // check for decimal, check SV if missing
1147 if(*sitr == '.') {
1148 ++sitr;
1149 parse_frac_type(sitr, stream_end, frac);
1150 // sitr will point to next expected char after this parsing
1151 // is complete so no need to advance it
1152 use_current_char = true;
1153 }
1154 else {
1155 return check_special_value(sitr, stream_end, t, c);
1156 }
1157 break;
1158 }
1159 case 'F':
1160 {
1161 // check for decimal, skip if missing
1162 if(*sitr == '.') {
1163 ++sitr;
1164 parse_frac_type(sitr, stream_end, frac);
1165 // sitr will point to next expected char after this parsing
1166 // is complete so no need to advance it
1167 use_current_char = true;
1168 }
1169 else {
1170 // nothing was parsed so we don't want to advance sitr
1171 use_current_char = true;
1172 }
1173 break;
1174 }
1175 // time_zone flags
1176 //case 'q':
1177 //case 'Q':
1178 //case 'z':
1179 case 'Z':
1180 {
1181 if(time_is_local) { // skip if 't' is a ptime
1182 ++itr;
1183 if(*itr == 'P') {
1184 // skip leading whitespace
1185 while((sitr != stream_end) && std::isspace(*sitr)) { ++sitr; }
1186 // parse zone
1187 while((sitr != stream_end) && (!std::isspace(*sitr))) {
1188 tz_str += *sitr;
1189 ++sitr;
1190 }
1191 }
1192 else {
1193 use_current_format_char = true;
1194 }
1195
1196 }
1197 else {
1198 // nothing was parsed so we don't want to advance sitr
1199 use_current_char = true;
1200 }
1201
1202 break;
1203 }
1204 default:
1205 {} // ignore what we don't understand?
1206 }// switch
1207 }
1208 else { // itr == '%', second consecutive
1209 ++sitr;
1210 }
1211
1212 if(use_current_format_char) {
1213 use_current_format_char = false;
1214 }
1215 else {
1216 ++itr; //advance past format specifier
1217 }
1218
1219 }
1220 else { //skip past chars in format and in buffer
1221 ++itr;
1222 // set use_current_char when sitr is already
1223 // pointing at the next character to process
1224 if (use_current_char) {
1225 use_current_char = false;
1226 }
1227 else {
1228 ++sitr;
1229 }
1230 }
1231 }
1232
1233 date_type d(not_a_date_time);
1234 if (day_of_year > 0) {
11fdf7f2 1235 d = date_type(static_cast<unsigned short>(t_year),1,1) + date_duration_type(day_of_year-1);
7c673cae
FG
1236 }
1237 else {
1238 d = date_type(t_year, t_month, t_day);
1239 }
1240
1241 time_duration_type td(hour, min, sec, frac);
1242 t = time_type(d, td);
1243 return sitr;
1244 }
1245
1246 //! Helper function to check for special_value
1247 /*! First character may have been consumed during original parse
1248 * attempt. Parameter 'c' should be a copy of that character.
1249 * Throws ios_base::failure if parse fails. */
1250 template<class temporal_type>
1251 inline
1252 InItrT check_special_value(InItrT& sitr,InItrT& stream_end, temporal_type& tt, char_type c='\0') const
1253 {
1254 match_results mr;
1255 if((c == '-' || c == '+') && (*sitr != c)) { // was the first character consumed?
1256 mr.cache += c;
1257 }
11fdf7f2 1258 (void)this->m_sv_parser.match(sitr, stream_end, mr);
7c673cae
FG
1259 if(mr.current_match == match_results::PARSE_ERROR) {
1260 std::string tmp = convert_string_type<char_type, char>(mr.cache);
1261 boost::throw_exception(std::ios_base::failure("Parse failed. No match found for '" + tmp + "'"));
1262 BOOST_DATE_TIME_UNREACHABLE_EXPRESSION(return sitr); // should never reach
1263 }
1264 tt = temporal_type(static_cast<special_values>(mr.current_match));
1265 return sitr;
1266 }
1267
1268 //! Helper function for parsing a fractional second type from the stream
1269 void parse_frac_type(InItrT& sitr,
1270 InItrT& stream_end,
1271 fracional_seconds_type& frac) const
1272 {
1273 string_type cache;
1274 while((sitr != stream_end) && std::isdigit(*sitr)) {
1275 cache += *sitr;
1276 ++sitr;
1277 }
1278 if(cache.size() > 0) {
1279 unsigned short precision = time_duration_type::num_fractional_digits();
1280 // input may be only the first few decimal places
1281 if(cache.size() < precision) {
1282 frac = lexical_cast<fracional_seconds_type>(cache);
1283 frac = decimal_adjust(frac, static_cast<unsigned short>(precision - cache.size()));
1284 }
1285 else {
1286 // if input has too many decimal places, drop excess digits
1287 frac = lexical_cast<fracional_seconds_type>(cache.substr(0, precision));
1288 }
1289 }
1290 }
1291
1292 private:
1293 string_type m_time_duration_format;
1294
1295 //! Helper function to adjust trailing zeros when parsing fractional digits
1296 template<class int_type>
1297 inline
1298 int_type decimal_adjust(int_type val, const unsigned short places) const
1299 {
1300 unsigned long factor = 1;
1301 for(int i = 0; i < places; ++i){
1302 factor *= 10; // shift decimal to the right
1303 }
1304 return val * factor;
1305 }
1306
1307 };
1308
1309template <class time_type, class CharT, class InItrT>
1310 std::locale::id time_input_facet<time_type, CharT, InItrT>::id;
1311
1312template <class time_type, class CharT, class InItrT>
1313 const typename time_input_facet<time_type, CharT, InItrT>::char_type*
1314 time_input_facet<time_type, CharT, InItrT>::fractional_seconds_format = time_formats<CharT>::fractional_seconds_format;
1315
1316 template <class time_type, class CharT, class InItrT>
1317 const typename time_input_facet<time_type, CharT, InItrT>::char_type*
1318 time_input_facet<time_type, CharT, InItrT>::fractional_seconds_or_none_format = time_formats<CharT>::fractional_seconds_or_none_format;
1319
1320 template <class time_type, class CharT, class InItrT>
1321 const typename time_input_facet<time_type, CharT, InItrT>::char_type*
1322 time_input_facet<time_type, CharT, InItrT>::seconds_with_fractional_seconds_format = time_formats<CharT>::seconds_with_fractional_seconds_format;
1323
1324 template <class time_type, class CharT, class InItrT>
1325 const typename time_input_facet<time_type, CharT, InItrT>::char_type*
1326 time_input_facet<time_type, CharT, InItrT>::seconds_format = time_formats<CharT>::seconds_format;
1327
1328 template <class time_type, class CharT, class InItrT>
1329 const typename time_input_facet<time_type, CharT, InItrT>::char_type*
1330 time_input_facet<time_type, CharT, InItrT>::standard_format = time_formats<CharT>::standard_format;
1331
1332 template <class time_type, class CharT, class InItrT>
1333 const typename time_input_facet<time_type, CharT, InItrT>::char_type*
1334 time_input_facet<time_type, CharT, InItrT>::zone_abbrev_format = time_formats<CharT>::zone_abbrev_format;
1335
1336 template <class time_type, class CharT, class InItrT>
1337 const typename time_input_facet<time_type, CharT, InItrT>::char_type*
1338 time_input_facet<time_type, CharT, InItrT>::zone_name_format = time_formats<CharT>::zone_name_format;
1339
1340 template <class time_type, class CharT, class InItrT>
1341 const typename time_input_facet<time_type, CharT, InItrT>::char_type*
1342 time_input_facet<time_type, CharT, InItrT>::zone_iso_format = time_formats<CharT>::zone_iso_format;
1343
1344 template <class time_type, class CharT, class InItrT>
1345 const typename time_input_facet<time_type, CharT, InItrT>::char_type*
1346 time_input_facet<time_type, CharT, InItrT>::zone_iso_extended_format = time_formats<CharT>::zone_iso_extended_format;
1347
1348 template <class time_type, class CharT, class InItrT>
1349 const typename time_input_facet<time_type, CharT, InItrT>::char_type*
1350 time_input_facet<time_type, CharT, InItrT>::duration_seperator = time_formats<CharT>::duration_seperator;
1351
1352 template <class time_type, class CharT, class InItrT>
1353 const typename time_input_facet<time_type, CharT, InItrT>::char_type*
1354 time_input_facet<time_type, CharT, InItrT>::iso_time_format_specifier = time_formats<CharT>::iso_time_format_specifier;
1355
1356 template <class time_type, class CharT, class InItrT>
1357 const typename time_input_facet<time_type, CharT, InItrT>::char_type*
1358 time_input_facet<time_type, CharT, InItrT>::iso_time_format_extended_specifier = time_formats<CharT>::iso_time_format_extended_specifier;
1359
1360 template <class time_type, class CharT, class InItrT>
1361 const typename time_input_facet<time_type, CharT, InItrT>::char_type*
1362 time_input_facet<time_type, CharT, InItrT>::default_time_input_format = time_formats<CharT>::default_time_input_format;
1363
1364 template <class time_type, class CharT, class InItrT>
1365 const typename time_input_facet<time_type, CharT, InItrT>::char_type*
1366 time_input_facet<time_type, CharT, InItrT>::default_time_duration_format = time_formats<CharT>::default_time_duration_format;
1367
7c673cae
FG
1368} } // namespaces
1369
7c673cae 1370#endif