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