LCOV - code coverage report
Current view: top level - usr/include/boost/date_time - time_facet.hpp (source / functions) Hit Total Coverage
Test: ROSE Lines: 0 79 0.0 %
Date: 2022-12-08 13:48:47 Functions: 0 7 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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>
      14             : #include <locale>
      15             : #include <limits>
      16             : #include <string>
      17             : #include <sstream>
      18             : #include <iomanip>
      19             : #include <iterator> // i/ostreambuf_iterator
      20             : #include <exception>
      21             : #include <boost/assert.hpp>
      22             : #include <boost/lexical_cast.hpp>
      23             : #include <boost/throw_exception.hpp>
      24             : #include <boost/range/as_literal.hpp>
      25             : #include <boost/algorithm/string/erase.hpp>
      26             : #include <boost/algorithm/string/replace.hpp>
      27             : #include <boost/date_time/compiler_config.hpp>
      28             : #include <boost/date_time/date_facet.hpp>
      29             : #include <boost/date_time/string_convert.hpp>
      30             : #include <boost/date_time/special_defs.hpp>
      31             : #include <boost/date_time/time_resolution_traits.hpp> // absolute_value
      32             : 
      33             : namespace boost {
      34             : namespace date_time {
      35             : 
      36             :   template <class CharT>
      37             :   struct time_formats {
      38             :     public:
      39             :       typedef CharT char_type;
      40             :       static const char_type fractional_seconds_format[3];               // f
      41             :       static const char_type fractional_seconds_or_none_format[3];       // F
      42             :       static const char_type seconds_with_fractional_seconds_format[3];  // s
      43             :       static const char_type seconds_format[3];                          // S
      44             :       static const char_type hours_format[3];                            // H
      45             :       static const char_type unrestricted_hours_format[3];               // O
      46             :       static const char_type full_24_hour_time_format[3];                // T
      47             :       static const char_type full_24_hour_time_expanded_format[9];       // HH:MM:SS
      48             :       static const char_type short_24_hour_time_format[3];               // R
      49             :       static const char_type short_24_hour_time_expanded_format[6];      // HH:MM
      50             :       static const char_type standard_format[9];                         // x X
      51             :       static const char_type zone_abbrev_format[3];                      // z
      52             :       static const char_type zone_name_format[3];                        // Z
      53             :       static const char_type zone_iso_format[3];                         // q
      54             :       static const char_type zone_iso_extended_format[3];                // Q
      55             :       static const char_type posix_zone_string_format[4];                // ZP
      56             :       static const char_type duration_sign_negative_only[3];             // -
      57             :       static const char_type duration_sign_always[3];                    // +
      58             :       static const char_type duration_seperator[2];
      59             :       static const char_type negative_sign[2];                           //-
      60             :       static const char_type positive_sign[2];                           //+
      61             :       static const char_type iso_time_format_specifier[18];
      62             :       static const char_type iso_time_format_extended_specifier[22];
      63             :       //default ptime format is YYYY-Mon-DD HH:MM:SS[.fff...][ zzz]
      64             :       static const char_type default_time_format[23];
      65             :       // default_time_input_format uses a posix_time_zone_string instead of a time zone abbrev
      66             :       static const char_type default_time_input_format[24];
      67             :       //default time_duration format is HH:MM:SS[.fff...]
      68             :       static const char_type default_time_duration_format[11];
      69             :   };
      70             : 
      71             :   template <class CharT>
      72             :   const typename time_formats<CharT>::char_type
      73             :   time_formats<CharT>::fractional_seconds_format[3] = {'%','f'};
      74             : 
      75             :   template <class CharT>
      76             :   const typename time_formats<CharT>::char_type
      77             :   time_formats<CharT>::fractional_seconds_or_none_format[3] = {'%','F'};
      78             : 
      79             :   template <class CharT>
      80             :   const typename time_formats<CharT>::char_type
      81             :   time_formats<CharT>::seconds_with_fractional_seconds_format[3] = {'%','s'};
      82             : 
      83             :   template <class CharT>
      84             :   const typename time_formats<CharT>::char_type
      85             :   time_formats<CharT>::seconds_format[3] =  {'%','S'};
      86             : 
      87             :   template <class CharT>
      88             :   const typename time_formats<CharT>::char_type
      89             :   time_formats<CharT>::hours_format[3] =  {'%','H'};
      90             : 
      91             :   template <class CharT>
      92             :   const typename time_formats<CharT>::char_type
      93             :   time_formats<CharT>::unrestricted_hours_format[3] =  {'%','O'};
      94             : 
      95             :   template <class CharT>
      96             :   const typename time_formats<CharT>::char_type
      97             :   time_formats<CharT>::full_24_hour_time_format[3] =  {'%','T'};
      98             : 
      99             :   template <class CharT>
     100             :   const typename time_formats<CharT>::char_type
     101             :   time_formats<CharT>::full_24_hour_time_expanded_format[9] =
     102             :   {'%','H',':','%','M',':','%','S'};
     103             : 
     104             :   template <class CharT>
     105             :   const typename time_formats<CharT>::char_type
     106             :   time_formats<CharT>::short_24_hour_time_format[3] =  {'%','R'};
     107             : 
     108             :   template <class CharT>
     109             :   const typename time_formats<CharT>::char_type
     110             :   time_formats<CharT>::short_24_hour_time_expanded_format[6] =
     111             :   {'%','H',':','%','M'};
     112             : 
     113             :   template <class CharT>
     114             :   const typename time_formats<CharT>::char_type
     115             :   //time_formats<CharT>::standard_format[5] =  {'%','c',' ','%','z'};
     116             :   time_formats<CharT>::standard_format[9] =  {'%','x',' ','%','X',' ','%','z'};
     117             : 
     118             :   template <class CharT>
     119             :   const typename time_formats<CharT>::char_type
     120             :   time_formats<CharT>::zone_abbrev_format[3] =  {'%','z'};
     121             : 
     122             :   template <class CharT>
     123             :   const typename time_formats<CharT>::char_type
     124             :   time_formats<CharT>::zone_name_format[3] =  {'%','Z'};
     125             : 
     126             :   template <class CharT>
     127             :   const typename time_formats<CharT>::char_type
     128             :   time_formats<CharT>::zone_iso_format[3] =  {'%','q'};
     129             : 
     130             :   template <class CharT>
     131             :   const typename time_formats<CharT>::char_type
     132             :   time_formats<CharT>::zone_iso_extended_format[3] ={'%','Q'};
     133             : 
     134             :   template <class CharT>
     135             :   const typename time_formats<CharT>::char_type
     136             :   time_formats<CharT>::posix_zone_string_format[4] ={'%','Z','P'};
     137             : 
     138             :   template <class CharT>
     139             :   const typename time_formats<CharT>::char_type
     140             :   time_formats<CharT>::duration_seperator[2] =  {':'};
     141             : 
     142             :   template <class CharT>
     143             :   const typename time_formats<CharT>::char_type
     144             :   time_formats<CharT>::negative_sign[2] =  {'-'};
     145             : 
     146             :   template <class CharT>
     147             :   const typename time_formats<CharT>::char_type
     148             :   time_formats<CharT>::positive_sign[2] =  {'+'};
     149             : 
     150             :   template <class CharT>
     151             :   const typename time_formats<CharT>::char_type
     152             :   time_formats<CharT>::duration_sign_negative_only[3] ={'%','-'};
     153             : 
     154             :   template <class CharT>
     155             :   const typename time_formats<CharT>::char_type
     156             :   time_formats<CharT>::duration_sign_always[3] ={'%','+'};
     157             : 
     158             :   template <class CharT>
     159             :   const typename time_formats<CharT>::char_type
     160             :   time_formats<CharT>::iso_time_format_specifier[18] =
     161             :     {'%', 'Y', '%', 'm', '%', 'd', 'T',
     162             :      '%', 'H', '%', 'M', '%', 'S', '%', 'F', '%','q' };
     163             : 
     164             :   template <class CharT>
     165             :   const typename time_formats<CharT>::char_type
     166             :   time_formats<CharT>::iso_time_format_extended_specifier[22] =
     167             :     {'%', 'Y', '-', '%', 'm', '-', '%', 'd', ' ',
     168             :      '%', 'H', ':', '%', 'M', ':', '%', 'S', '%', 'F','%','Q'};
     169             : 
     170             :   template <class CharT>
     171             :   const typename time_formats<CharT>::char_type
     172             :   time_formats<CharT>::default_time_format[23] =
     173             :     {'%','Y','-','%','b','-','%','d',' ',
     174             :       '%','H',':','%','M',':','%','S','%','F',' ','%','z'};
     175             : 
     176             :   template <class CharT>
     177             :   const typename time_formats<CharT>::char_type
     178             :   time_formats<CharT>::default_time_input_format[24] =
     179             :     {'%','Y','-','%','b','-','%','d',' ',
     180             :       '%','H',':','%','M',':','%','S','%','F',' ','%','Z','P'};
     181             : 
     182             :   template <class CharT>
     183             :   const typename time_formats<CharT>::char_type
     184             :   time_formats<CharT>::default_time_duration_format[11] =
     185             :     {'%','O',':','%','M',':','%','S','%','F'};
     186             : 
     187             : 
     188             : 
     189             :   /*! Facet used for format-based output of time types
     190             :    * This class provides for the use of format strings to output times.  In addition
     191             :    * to the flags for formatting date elements, the following are the allowed format flags:
     192             :    *  - %x %X => default format - enables addition of more flags to default (ie. "%x %X %z")
     193             :    *  - %f => fractional seconds ".123456"
     194             :    *  - %F => fractional seconds or none: like frac sec but empty if frac sec == 0
     195             :    *  - %s => seconds w/ fractional sec "02.123" (this is the same as "%S%f)
     196             :    *  - %S => seconds "02"
     197             :    *  - %z => abbreviated time zone "EDT"
     198             :    *  - %Z => full time zone name "Eastern Daylight Time"
     199             :    */
     200             :   template <class time_type,
     201             :             class CharT,
     202             :             class OutItrT = std::ostreambuf_iterator<CharT, std::char_traits<CharT> > >
     203             :   class BOOST_SYMBOL_VISIBLE 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           0 :     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           0 :         m_time_duration_format(string_type(duration_sign_negative_only) + default_time_duration_format)
     250           0 :     {}
     251             : 
     252             :     //! Construct the facet with an explicitly specified format
     253           0 :     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           0 :         m_time_duration_format(string_type(duration_sign_negative_only) + default_time_duration_format)
     264           0 :     {}
     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           0 :     virtual void set_iso_format()
     273             :     {
     274           0 :       this->m_format = iso_time_format_specifier;
     275           0 :     }
     276           0 :     virtual void set_iso_extended_format()
     277             :     {
     278           0 :       this->m_format = iso_time_format_extended_specifier;
     279           0 :     }
     280             : 
     281           0 :     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           0 :       if (time_arg.is_special()) {
     287             :         return this->do_put_special(next_arg, ios_arg, fill_arg,
     288           0 :                               time_arg.date().as_special());
     289             :       }
     290           0 :       string_type local_format(this->m_format);
     291             : 
     292             :       // %T and %R have to be replaced here since they are not standard
     293           0 :       boost::algorithm::replace_all(local_format,
     294           0 :         boost::as_literal(formats_type::full_24_hour_time_format),
     295           0 :         boost::as_literal(formats_type::full_24_hour_time_expanded_format));
     296           0 :       boost::algorithm::replace_all(local_format,
     297           0 :         boost::as_literal(formats_type::short_24_hour_time_format),
     298           0 :         boost::as_literal(formats_type::short_24_hour_time_expanded_format));
     299             : 
     300           0 :       string_type frac_str;
     301           0 :       if (local_format.find(seconds_with_fractional_seconds_format) != string_type::npos) {
     302             :         // replace %s with %S.nnn
     303           0 :         frac_str =
     304             :           fractional_seconds_as_string(time_arg.time_of_day(), false);
     305           0 :         char_type sep = std::use_facet<std::numpunct<char_type> >(ios_arg.getloc()).decimal_point();
     306             : 
     307           0 :         string_type replace_string(seconds_format);
     308           0 :         replace_string += sep;
     309           0 :         replace_string += frac_str;
     310           0 :         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           0 :       if (local_format.find(posix_zone_string_format) != string_type::npos) {
     318           0 :         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           0 :           boost::algorithm::erase_all(local_format, posix_zone_string_format);
     322             :         }
     323             :         else{
     324           0 :           boost::algorithm::replace_all(local_format,
     325             :                                         posix_zone_string_format,
     326             :                                         time_arg.zone_as_posix_string());
     327             :         }
     328             :       }
     329           0 :       if (local_format.find(zone_name_format) != string_type::npos) {
     330           0 :         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           0 :           std::basic_ostringstream<char_type> ss;
     338           0 :           ss << ' ' << zone_name_format;
     339           0 :           boost::algorithm::erase_all(local_format, ss.str());
     340             :         }
     341             :         else{
     342           0 :           boost::algorithm::replace_all(local_format,
     343             :                                         zone_name_format,
     344             :                                         time_arg.zone_name());
     345             :         }
     346             :       }
     347           0 :       if (local_format.find(zone_abbrev_format) != string_type::npos) {
     348           0 :         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           0 :           std::basic_ostringstream<char_type> ss;
     356           0 :           ss << ' ' << zone_abbrev_format;
     357           0 :           boost::algorithm::erase_all(local_format, ss.str());
     358             :         }
     359             :         else{
     360           0 :           boost::algorithm::replace_all(local_format,
     361             :                                         zone_abbrev_format,
     362             :                                         time_arg.zone_abbrev(false));
     363             :         }
     364             :       }
     365           0 :       if (local_format.find(zone_iso_extended_format) != string_type::npos) {
     366           0 :         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           0 :           boost::algorithm::erase_all(local_format, zone_iso_extended_format);
     374             :         }
     375             :         else{
     376           0 :           boost::algorithm::replace_all(local_format,
     377             :                                         zone_iso_extended_format,
     378             :                                         time_arg.zone_name(true));
     379             :         }
     380             :       }
     381             : 
     382           0 :       if (local_format.find(zone_iso_format) != string_type::npos) {
     383           0 :         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           0 :           boost::algorithm::erase_all(local_format, zone_iso_format);
     391             :         }
     392             :         else{
     393           0 :           boost::algorithm::replace_all(local_format,
     394             :                                         zone_iso_format,
     395             :                                         time_arg.zone_abbrev(true));
     396             :         }
     397             :       }
     398           0 :       if (local_format.find(fractional_seconds_format) != string_type::npos) {
     399             :         // replace %f with nnnnnnn
     400           0 :         if (frac_str.empty()) {
     401           0 :           frac_str = fractional_seconds_as_string(time_arg.time_of_day(), false);
     402             :         }
     403           0 :         boost::algorithm::replace_all(local_format,
     404             :                                       fractional_seconds_format,
     405             :                                       frac_str);
     406             :       }
     407             : 
     408           0 :       if (local_format.find(fractional_seconds_or_none_format) != string_type::npos) {
     409             :         // replace %F with nnnnnnn or nothing if fs == 0
     410           0 :         frac_str =
     411             :           fractional_seconds_as_string(time_arg.time_of_day(), true);
     412           0 :         if (frac_str.size()) {
     413           0 :           char_type sep = std::use_facet<std::numpunct<char_type> >(ios_arg.getloc()).decimal_point();
     414           0 :           string_type replace_string;
     415           0 :           replace_string += sep;
     416           0 :           replace_string += frac_str;
     417           0 :           boost::algorithm::replace_all(local_format,
     418             :                                         fractional_seconds_or_none_format,
     419             :                                         replace_string);
     420             :         }
     421             :         else {
     422           0 :           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           0 :                        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           0 :     fractional_seconds_as_string(const time_duration_type& time_arg,
     552             :                                  bool null_when_zero)
     553             :     {
     554           0 :       typename time_duration_type::fractional_seconds_type frac_sec =
     555             :         time_arg.fractional_seconds();
     556             : 
     557           0 :       if (null_when_zero && (frac_sec == 0)) {
     558           0 :         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           0 :         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           0 :     integral_as_string(IntT val, int width = 2)
     578             :     {
     579           0 :       std::basic_ostringstream<char_type> ss;
     580           0 :       ss.imbue(std::locale::classic()); // don't want any formatting
     581             :       ss << std::setw(width)
     582           0 :         << 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           0 :       ss << val;
     589             : #endif
     590           0 :       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 BOOST_SYMBOL_VISIBLE time_input_facet :
     697             :     public boost::date_time::date_input_facet<typename time_type::date_type , CharT, InItrT> {
     698             :     public:
     699             :       typedef typename time_type::date_type date_type;
     700             :       typedef typename time_type::time_duration_type time_duration_type;
     701             :       typedef typename time_duration_type::fractional_seconds_type fracional_seconds_type;
     702             :       typedef boost::date_time::period<time_type,time_duration_type> period_type;
     703             :       typedef boost::date_time::date_input_facet<typename time_type::date_type, CharT, InItrT> base_type;
     704             :       typedef typename base_type::duration_type date_duration_type;
     705             :       typedef typename base_type::year_type year_type;
     706             :       typedef typename base_type::month_type month_type;
     707             :       typedef typename base_type::day_type day_type;
     708             :       typedef typename base_type::string_type string_type;
     709             :       typedef typename string_type::const_iterator const_itr;
     710             :       typedef typename base_type::char_type   char_type;
     711             :       typedef typename base_type::format_date_parser_type format_date_parser_type;
     712             :       typedef typename base_type::period_parser_type period_parser_type;
     713             :       typedef typename base_type::special_values_parser_type special_values_parser_type;
     714             :       typedef typename base_type::date_gen_parser_type date_gen_parser_type;
     715             :       typedef typename base_type::special_values_parser_type::match_results match_results;
     716             : 
     717             :       static const char_type* fractional_seconds_format;                // f
     718             :       static const char_type* fractional_seconds_or_none_format;        // F
     719             :       static const char_type* seconds_with_fractional_seconds_format;   // s
     720             :       static const char_type* seconds_format;                           // S
     721             :       static const char_type* standard_format;                          // x X
     722             :       static const char_type* zone_abbrev_format;                       // z
     723             :       static const char_type* zone_name_format;                         // Z
     724             :       static const char_type* zone_iso_format;                          // q
     725             :       static const char_type* zone_iso_extended_format;                 // Q
     726             :       static const char_type* duration_seperator;
     727             :       static const char_type* iso_time_format_specifier;
     728             :       static const char_type* iso_time_format_extended_specifier;
     729             :       static const char_type* default_time_input_format;
     730             :       static const char_type* default_time_duration_format;
     731             :       static std::locale::id id;
     732             : 
     733             :       //! Constructor that takes a format string for a ptime
     734             :       explicit time_input_facet(const string_type& format, ::size_t ref_arg = 0)
     735             :         : base_type(format, ref_arg),
     736             :           m_time_duration_format(default_time_duration_format)
     737             :       { }
     738             : 
     739             :       explicit time_input_facet(const string_type& format,
     740             :                                 const format_date_parser_type& date_parser,
     741             :                                 const special_values_parser_type& sv_parser,
     742             :                                 const period_parser_type& per_parser,
     743             :                                 const date_gen_parser_type& date_gen_parser,
     744             :                                 ::size_t ref_arg = 0)
     745             :         : base_type(format,
     746             :                     date_parser,
     747             :                     sv_parser,
     748             :                     per_parser,
     749             :                     date_gen_parser,
     750             :                     ref_arg),
     751             :           m_time_duration_format(default_time_duration_format)
     752             :       {}
     753             : 
     754             :       //! sets default formats for ptime, local_date_time, and time_duration
     755             :       explicit time_input_facet(::size_t ref_arg = 0)
     756             :         : base_type(default_time_input_format, ref_arg),
     757             :           m_time_duration_format(default_time_duration_format)
     758             :       { }
     759             : 
     760             :       //! Set the format for time_duration
     761             :       void time_duration_format(const char_type* const format) {
     762             :         m_time_duration_format = format;
     763             :       }
     764             :       virtual void set_iso_format()
     765             :       {
     766             :         this->m_format = iso_time_format_specifier;
     767             :       }
     768             :       virtual void set_iso_extended_format()
     769             :       {
     770             :         this->m_format = iso_time_format_extended_specifier;
     771             :       }
     772             : 
     773             :       InItrT get(InItrT& sitr,
     774             :                  InItrT& stream_end,
     775             :                  std::ios_base& ios_arg,
     776             :                  period_type& p) const
     777             :       {
     778             :         p = this->m_period_parser.get_period(sitr,
     779             :                                              stream_end,
     780             :                                              ios_arg,
     781             :                                              p,
     782             :                                              time_duration_type::unit(),
     783             :                                              *this);
     784             :         return sitr;
     785             :       }
     786             : 
     787             :       //default ptime format is YYYY-Mon-DD HH:MM:SS[.fff...][ zzz]
     788             :       //default time_duration format is %H:%M:%S%F HH:MM:SS[.fff...]
     789             : 
     790             :       InItrT get(InItrT& sitr,
     791             :                  InItrT& stream_end,
     792             :                  std::ios_base& ios_arg,
     793             :                  time_duration_type& td) const
     794             :       {
     795             :         // skip leading whitespace
     796             :         while((sitr != stream_end) && std::isspace(*sitr)) { ++sitr; }
     797             : 
     798             :         bool use_current_char = false;
     799             : 
     800             :         // num_get will consume the +/-, we may need a copy if special_value
     801             :         char_type c = '\0';
     802             :         if((sitr != stream_end) && (*sitr == '-' || *sitr == '+')) {
     803             :           c = *sitr;
     804             :         }
     805             : 
     806             :         typedef typename time_duration_type::hour_type hour_type;
     807             :         typedef typename time_duration_type::min_type min_type;
     808             :         typedef typename time_duration_type::sec_type sec_type;
     809             : 
     810             :         hour_type hour = 0;
     811             :         min_type min = 0;
     812             :         sec_type sec = 0;
     813             :         typename time_duration_type::fractional_seconds_type frac(0);
     814             : 
     815             :         typedef std::num_get<CharT, InItrT> num_get;
     816             :         if(!std::has_facet<num_get>(ios_arg.getloc())) {
     817             :           num_get* ng = new num_get();
     818             :           std::locale loc = std::locale(ios_arg.getloc(), ng);
     819             :           ios_arg.imbue(loc);
     820             :         }
     821             : 
     822             :         const_itr itr(m_time_duration_format.begin());
     823             :         while (itr != m_time_duration_format.end() && (sitr != stream_end)) {
     824             :           if (*itr == '%') {
     825             :             if (++itr == m_time_duration_format.end()) break;
     826             :             if (*itr != '%') {
     827             :               switch(*itr) {
     828             :               case 'O':
     829             :                 {
     830             :                   // A period may span more than 24 hours. In that case the format
     831             :                   // string should be composed with the unrestricted hours specifier.
     832             :                   hour = var_string_to_int<hour_type, CharT>(sitr, stream_end,
     833             :                                       std::numeric_limits<hour_type>::digits10 + 1);
     834             :                   if(hour == -1){
     835             :                      return check_special_value(sitr, stream_end, td, c);
     836             :                   }
     837             :                   break;
     838             :                 }
     839             :               case 'H':
     840             :                 {
     841             :                   match_results mr;
     842             :                   hour = fixed_string_to_int<hour_type, CharT>(sitr, stream_end, mr, 2);
     843             :                   if(hour == -1){
     844             :                      return check_special_value(sitr, stream_end, td, c);
     845             :                   }
     846             :                   break;
     847             :                 }
     848             :               case 'M':
     849             :                 {
     850             :                   match_results mr;
     851             :                   min = fixed_string_to_int<min_type, CharT>(sitr, stream_end, mr, 2);
     852             :                   if(min == -1){
     853             :                      return check_special_value(sitr, stream_end, td, c);
     854             :                   }
     855             :                   break;
     856             :                 }
     857             :               case 's':
     858             :               case 'S':
     859             :                 {
     860             :                   match_results mr;
     861             :                   sec = fixed_string_to_int<sec_type, CharT>(sitr, stream_end, mr, 2);
     862             :                   if(sec == -1){
     863             :                      return check_special_value(sitr, stream_end, td, c);
     864             :                   }
     865             :                   if (*itr == 'S')
     866             :                     break;
     867             :                   // %s is the same as %S%f so we drop through into %f
     868             :                 }
     869             :                 /* Falls through. */
     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;
     961             :         bool use_current_format_char = false; // used whith two character flags
     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':
    1092             :                 case 'e':
    1093             :                   {
    1094             :                     try {
    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);
    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             :                   }
    1143             :                   /* Falls through. */
    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) {
    1235             :           d = date_type(static_cast<unsigned short>(t_year),1,1) + date_duration_type(day_of_year-1);
    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             :         }
    1258             :         (void)this->m_sv_parser.match(sitr, stream_end, mr);
    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             : 
    1309             : template <class time_type, class CharT, class InItrT>
    1310             :   std::locale::id time_input_facet<time_type, CharT, InItrT>::id;
    1311             : 
    1312             : template <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             : 
    1368             : 
    1369             : } } // namespaces
    1370             : 
    1371             : 
    1372             : #endif
    1373             : 

Generated by: LCOV version 1.14