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