New URL for NEMO forge!   http://forge.nemo-ocean.eu

Since March 2022 along with NEMO 4.2 release, the code development moved to a self-hosted GitLab.
This present forge is now archived and remained online for history.
time_facet.hpp in vendors/XIOS/current/extern/boost/include/boost/date_time – NEMO

source: vendors/XIOS/current/extern/boost/include/boost/date_time/time_facet.hpp @ 3408

Last change on this file since 3408 was 3408, checked in by rblod, 12 years ago

importing initial XIOS vendor drop

  • Property svn:keywords set to Id
File size: 56.9 KB
Line 
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: 2010-06-09 12:39:31 -0400 (Wed, 09 Jun 2010) $
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
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> > >
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 a_ref = 0)
248      : base_type(default_time_format, period_formatter_type(), special_values_formatter_type(), date_gen_formatter_type(), a_ref),
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* a_format,
254                        period_formatter_type period_formatter = 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 a_ref = 0)
258      : base_type(a_format,
259                  period_formatter,
260                  special_value_formatter,
261                  dg_formatter,
262                  a_ref),
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 a_next,
282                std::ios_base& a_ios,
283                char_type a_fill,
284                const time_type& a_time) const
285    {
286      if (a_time.is_special()) {
287        return this->do_put_special(a_next, a_ios, a_fill,
288                              a_time.date().as_special());
289      }
290      string_type format(this->m_format);
291
292      // %T and %R have to be replaced here since they are not standard
293      boost::algorithm::replace_all(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(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 (format.find(seconds_with_fractional_seconds_format) != string_type::npos) {
302        // replace %s with %S.nnn
303        frac_str =
304          fractional_seconds_as_string(a_time.time_of_day(), false);
305        char_type sep = std::use_facet<std::numpunct<char_type> >(a_ios.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(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 (format.find(posix_zone_string_format) != string_type::npos) {
318        if(a_time.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(format, posix_zone_string_format);
322        }
323        else{
324          boost::algorithm::replace_all(format,
325                                        posix_zone_string_format,
326                                        a_time.zone_as_posix_string());
327        }
328      }
329      if (format.find(zone_name_format) != string_type::npos) {
330        if(a_time.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(format, ss.str());
340        }
341        else{
342          boost::algorithm::replace_all(format,
343                                        zone_name_format,
344                                        a_time.zone_name());
345        }
346      }
347      if (format.find(zone_abbrev_format) != string_type::npos) {
348        if(a_time.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(format, ss.str());
358        }
359        else{
360          boost::algorithm::replace_all(format,
361                                        zone_abbrev_format,
362                                        a_time.zone_abbrev(false));
363        }
364      }
365      if (format.find(zone_iso_extended_format) != string_type::npos) {
366        if(a_time.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(format, zone_iso_extended_format);
374        }
375        else{
376          boost::algorithm::replace_all(format,
377                                        zone_iso_extended_format,
378                                        a_time.zone_name(true));
379        }
380      }
381
382      if (format.find(zone_iso_format) != string_type::npos) {
383        if(a_time.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(format, zone_iso_format);
391        }
392        else{
393          boost::algorithm::replace_all(format,
394                                        zone_iso_format,
395                                        a_time.zone_abbrev(true));
396        }
397      }
398      if (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(a_time.time_of_day(), false);
402        }
403        boost::algorithm::replace_all(format,
404                                      fractional_seconds_format,
405                                      frac_str);
406      }
407
408      if (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(a_time.time_of_day(), true);
412        if (frac_str.size()) {
413          char_type sep = std::use_facet<std::numpunct<char_type> >(a_ios.getloc()).decimal_point();
414          string_type replace_string;
415          replace_string += sep;
416          replace_string += frac_str;
417          boost::algorithm::replace_all(format,
418                                        fractional_seconds_or_none_format,
419                                        replace_string);
420        }
421        else {
422          boost::algorithm::erase_all(format,
423                                      fractional_seconds_or_none_format);
424        }
425      }
426
427      return this->do_put_tm(a_next, a_ios, a_fill,
428                       to_tm(a_time), format);
429    }
430
431    //! put function for time_duration
432    OutItrT put(OutItrT a_next,
433                std::ios_base& a_ios,
434                char_type a_fill,
435                const time_duration_type& a_time_dur) const
436    {
437      if (a_time_dur.is_special()) {
438        return this->do_put_special(a_next, a_ios, a_fill,
439                              a_time_dur.get_rep().as_special());
440      }
441
442      string_type format(m_time_duration_format);
443      if (a_time_dur.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(a_time_dur);
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(a_time_dur);
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(a_time_dur, false);
498        char_type sep = std::use_facet<std::numpunct<char_type> >(a_ios.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(a_time_dur, 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(a_time_dur, true);
521        if (frac_str.size()) {
522          char_type sep = std::use_facet<std::numpunct<char_type> >(a_ios.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(a_next, a_ios, a_fill,
537                       to_tm(a_time_dur), format);
538    }
539
540    OutItrT put(OutItrT next, std::ios_base& a_ios,
541                char_type fill, const period_type& p) const
542    {
543      return this->m_period_formatter.put_period(next, a_ios, fill,p,*this);
544    }
545
546
547  protected:
548
549    static
550    string_type
551    fractional_seconds_as_string(const time_duration_type& a_time,
552                                 bool null_when_zero)
553    {
554      typename time_duration_type::fractional_seconds_type frac_sec =
555        a_time.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& a_time, int width = 2)
570    {
571      return integral_as_string(date_time::absolute_value(a_time.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 a_ref = 0)
735        : base_type(format, a_ref),
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 a_ref = 0)
745        : base_type(format,
746                    date_parser,
747                    sv_parser,
748                    per_parser,
749                    date_gen_parser,
750                    a_ref),
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 a_ref = 0)
756        : base_type(default_time_input_format, a_ref),
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& a_ios,
776                 period_type& p) const
777      {
778        p = this->m_period_parser.get_period(sitr,
779                                             stream_end,
780                                             a_ios,
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& a_ios,
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>(a_ios.getloc())) {
817          num_get* ng = new num_get();
818          std::locale loc = std::locale(a_ios.getloc(), ng);
819          a_ios.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            ++itr;
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& a_ios,
932                 time_type& t) const
933      {
934        string_type tz_str;
935        return get(sitr, stream_end, a_ios, 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& a_ios,
941                            time_type& t,
942                            string_type& tz_str) const
943      {
944        return get(sitr, stream_end, a_ios, t, tz_str, true);
945      }
946
947    protected:
948
949      InItrT get(InItrT& sitr,
950                 InItrT& stream_end,
951                 std::ios_base& a_ios,
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>(a_ios.getloc())) {
989          num_get* ng = new num_get();
990          std::locale loc = std::locale(a_ios.getloc(), ng);
991          a_ios.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            ++itr;
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
1303template <class time_type, class CharT, class InItrT>
1304  std::locale::id time_input_facet<time_type, CharT, InItrT>::id;
1305
1306template <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
Note: See TracBrowser for help on using the repository browser.