~ubuntu-branches/ubuntu/wily/davix/wily

« back to all changes in this revision

Viewing changes to deps/boost_intern/boost/date_time/time_facet.hpp

  • Committer: Package Import Robot
  • Author(s): Mattias Ellert
  • Date: 2015-07-31 13:17:55 UTC
  • mfrom: (5.1.3 sid)
  • Revision ID: package-import@ubuntu.com-20150731131755-mizprbmn7ogv33te
Tags: 0.4.1-1
* Update to version 0.4.1
* Implement Multi-Arch support

Show diffs side-by-side

added added

removed removed

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