1 | #ifndef _DATE_TIME_DATE_FACET__HPP___ |
2 | #define _DATE_TIME_DATE_FACET__HPP___ |
3 | |
4 | /* Copyright (c) 2004-2005 CrystalClear Software, Inc. |
5 | * Use, modification and distribution is subject to the |
6 | * Boost Software License, Version 1.0. (See accompanying |
7 | * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) |
8 | * Author: Martin Andrian, Jeff Garland, Bart Garst |
9 | * $Date$ |
10 | */ |
11 | |
12 | #include <iterator> // ostreambuf_iterator |
13 | #include <locale> |
14 | #include <string> |
15 | #include <vector> |
16 | #include <boost/throw_exception.hpp> |
17 | #include <boost/algorithm/string/replace.hpp> |
18 | #include <boost/date_time/compiler_config.hpp> |
19 | #include <boost/date_time/period.hpp> |
20 | #include <boost/date_time/special_defs.hpp> |
21 | #include <boost/date_time/special_values_formatter.hpp> |
22 | #include <boost/date_time/period_formatter.hpp> |
23 | #include <boost/date_time/period_parser.hpp> |
24 | #include <boost/date_time/date_generator_formatter.hpp> |
25 | #include <boost/date_time/date_generator_parser.hpp> |
26 | #include <boost/date_time/format_date_parser.hpp> |
27 | |
28 | namespace boost { namespace date_time { |
29 | |
30 | |
31 | /*! Class that provides format based I/O facet for date types. |
32 | * |
33 | * This class allows the formatting of dates by using format string. |
34 | * Format strings are: |
35 | * |
36 | * - %A => long_weekday_format - Full name Ex: Tuesday |
37 | * - %a => short_weekday_format - Three letter abbreviation Ex: Tue |
38 | * - %B => long_month_format - Full name Ex: October |
39 | * - %b => short_month_format - Three letter abbreviation Ex: Oct |
40 | * - %x => standard_format_specifier - defined by the locale |
41 | * - %Y-%b-%d => default_date_format - YYYY-Mon-dd |
42 | * |
43 | * Default month format == %b |
44 | * Default weekday format == %a |
45 | */ |
46 | template <class date_type, |
47 | class CharT, |
48 | class OutItrT = std::ostreambuf_iterator<CharT, std::char_traits<CharT> > > |
49 | class BOOST_SYMBOL_VISIBLE date_facet : public std::locale::facet { |
50 | public: |
51 | typedef typename date_type::duration_type duration_type; |
52 | // greg_weekday is gregorian_calendar::day_of_week_type |
53 | typedef typename date_type::day_of_week_type day_of_week_type; |
54 | typedef typename date_type::day_type day_type; |
55 | typedef typename date_type::month_type month_type; |
56 | typedef boost::date_time::period<date_type,duration_type> period_type; |
57 | typedef std::basic_string<CharT> string_type; |
58 | typedef CharT char_type; |
59 | typedef boost::date_time::period_formatter<CharT> period_formatter_type; |
60 | typedef boost::date_time::special_values_formatter<CharT> special_values_formatter_type; |
61 | typedef std::vector<std::basic_string<CharT> > input_collection_type; |
62 | // used for the output of the date_generators |
63 | typedef date_generator_formatter<date_type, CharT> date_gen_formatter_type; |
64 | typedef partial_date<date_type> partial_date_type; |
65 | typedef nth_kday_of_month<date_type> nth_kday_type; |
66 | typedef first_kday_of_month<date_type> first_kday_type; |
67 | typedef last_kday_of_month<date_type> last_kday_type; |
68 | typedef first_kday_after<date_type> kday_after_type; |
69 | typedef first_kday_before<date_type> kday_before_type; |
70 | static const char_type long_weekday_format[3]; |
71 | static const char_type short_weekday_format[3]; |
72 | static const char_type long_month_format[3]; |
73 | static const char_type short_month_format[3]; |
74 | static const char_type default_period_separator[4]; |
75 | static const char_type standard_format_specifier[3]; |
76 | static const char_type iso_format_specifier[7]; |
77 | static const char_type iso_format_extended_specifier[9]; |
78 | static const char_type default_date_format[9]; // YYYY-Mon-DD |
79 | static std::locale::id id; |
80 | |
81 | #if defined (__SUNPRO_CC) && defined (_RWSTD_VER) |
82 | std::locale::id& __get_id (void) const { return id; } |
83 | #endif |
84 | |
85 | explicit date_facet(::size_t a_ref = 0) |
86 | : std::locale::facet(a_ref), |
87 | //m_format(standard_format_specifier) |
88 | m_format(default_date_format), |
89 | m_month_format(short_month_format), |
90 | m_weekday_format(short_weekday_format) |
91 | {} |
92 | |
93 | explicit date_facet(const char_type* format_str, |
94 | const input_collection_type& short_names, |
95 | ::size_t ref_count = 0) |
96 | : std::locale::facet(ref_count), |
97 | m_format(format_str), |
98 | m_month_format(short_month_format), |
99 | m_weekday_format(short_weekday_format), |
100 | m_month_short_names(short_names) |
101 | {} |
102 | |
103 | |
104 | explicit date_facet(const char_type* format_str, |
105 | period_formatter_type per_formatter = period_formatter_type(), |
106 | special_values_formatter_type sv_formatter = special_values_formatter_type(), |
107 | date_gen_formatter_type dg_formatter = date_gen_formatter_type(), |
108 | ::size_t ref_count = 0) |
109 | : std::locale::facet(ref_count), |
110 | m_format(format_str), |
111 | m_month_format(short_month_format), |
112 | m_weekday_format(short_weekday_format), |
113 | m_period_formatter(per_formatter), |
114 | m_date_gen_formatter(dg_formatter), |
115 | m_special_values_formatter(sv_formatter) |
116 | {} |
117 | void format(const char_type* const format_str) { |
118 | m_format = format_str; |
119 | } |
120 | virtual void set_iso_format() |
121 | { |
122 | m_format = iso_format_specifier; |
123 | } |
124 | virtual void set_iso_extended_format() |
125 | { |
126 | m_format = iso_format_extended_specifier; |
127 | } |
128 | void month_format(const char_type* const format_str) { |
129 | m_month_format = format_str; |
130 | } |
131 | void weekday_format(const char_type* const format_str) { |
132 | m_weekday_format = format_str; |
133 | } |
134 | |
135 | void period_formatter(period_formatter_type per_formatter) { |
136 | m_period_formatter= per_formatter; |
137 | } |
138 | void special_values_formatter(const special_values_formatter_type& svf) |
139 | { |
140 | m_special_values_formatter = svf; |
141 | } |
142 | void short_weekday_names(const input_collection_type& short_names) |
143 | { |
144 | m_weekday_short_names = short_names; |
145 | } |
146 | void long_weekday_names(const input_collection_type& long_names) |
147 | { |
148 | m_weekday_long_names = long_names; |
149 | } |
150 | |
151 | void short_month_names(const input_collection_type& short_names) |
152 | { |
153 | m_month_short_names = short_names; |
154 | } |
155 | |
156 | void long_month_names(const input_collection_type& long_names) |
157 | { |
158 | m_month_long_names = long_names; |
159 | } |
160 | |
161 | void date_gen_phrase_strings(const input_collection_type& new_strings, |
162 | typename date_gen_formatter_type::phrase_elements beg_pos=date_gen_formatter_type::first) |
163 | { |
164 | m_date_gen_formatter.elements(new_strings, beg_pos); |
165 | } |
166 | |
167 | OutItrT put(OutItrT next, |
168 | std::ios_base& a_ios, |
169 | char_type fill_char, |
170 | const date_type& d) const |
171 | { |
172 | if (d.is_special()) { |
173 | return do_put_special(next, a_ios, fill_char, sv: d.as_special()); |
174 | } |
175 | //The following line of code required the date to support a to_tm function |
176 | return do_put_tm(next, a_ios, fill_char, tm_value: to_tm(d), a_format: m_format); |
177 | } |
178 | |
179 | OutItrT put(OutItrT next, |
180 | std::ios_base& a_ios, |
181 | char_type fill_char, |
182 | const duration_type& dd) const |
183 | { |
184 | if (dd.is_special()) { |
185 | return do_put_special(next, a_ios, fill_char, sv: dd.get_rep().as_special()); |
186 | } |
187 | |
188 | typedef std::num_put<CharT, OutItrT> num_put; |
189 | if (std::has_facet<num_put>(a_ios.getloc())) { |
190 | return std::use_facet<num_put>(a_ios.getloc()).put(next, a_ios, fill_char, dd.get_rep().as_number()); |
191 | } |
192 | else { |
193 | num_put* f = new num_put(); |
194 | std::locale l = std::locale(a_ios.getloc(), f); |
195 | a_ios.imbue(loc: l); |
196 | return f->put(next, a_ios, fill_char, dd.get_rep().as_number()); |
197 | } |
198 | |
199 | } |
200 | |
201 | |
202 | OutItrT put(OutItrT next, |
203 | std::ios_base& a_ios, |
204 | char_type fill_char, |
205 | const month_type& m) const |
206 | { |
207 | //if (d.is_special()) { |
208 | // return do_put_special(next, a_ios, fill_char, d.as_special()); |
209 | //} |
210 | //The following line of code required the date to support a to_tm function |
211 | std::tm dtm; |
212 | std::memset(s: &dtm, c: 0, n: sizeof(dtm)); |
213 | dtm.tm_mon = m - 1; |
214 | return do_put_tm(next, a_ios, fill_char, tm_value: dtm, a_format: m_month_format); |
215 | } |
216 | |
217 | //! puts the day of month |
218 | OutItrT put(OutItrT next, |
219 | std::ios_base& a_ios, |
220 | char_type fill_char, |
221 | const day_type& day) const |
222 | { |
223 | std::tm dtm; |
224 | std::memset(s: &dtm, c: 0, n: sizeof(dtm)); |
225 | dtm.tm_mday = day.as_number(); |
226 | char_type tmp[3] = {'%','d'}; |
227 | string_type temp_format(tmp); |
228 | return do_put_tm(next, a_ios, fill_char, tm_value: dtm, a_format: temp_format); |
229 | } |
230 | |
231 | OutItrT put(OutItrT next, |
232 | std::ios_base& a_ios, |
233 | char_type fill_char, |
234 | const day_of_week_type& dow) const |
235 | { |
236 | //if (d.is_special()) { |
237 | // return do_put_special(next, a_ios, fill_char, d.as_special()); |
238 | //} |
239 | //The following line of code required the date to support a to_tm function |
240 | std::tm dtm; |
241 | std::memset(s: &dtm, c: 0, n: sizeof(dtm)); |
242 | dtm.tm_wday = dow; |
243 | return do_put_tm(next, a_ios, fill_char, tm_value: dtm, a_format: m_weekday_format); |
244 | } |
245 | |
246 | |
247 | OutItrT put(OutItrT next, |
248 | std::ios_base& a_ios, |
249 | char_type fill_char, |
250 | const period_type& p) const |
251 | { |
252 | return m_period_formatter.put_period(next, a_ios, fill_char, p, *this); |
253 | } |
254 | |
255 | OutItrT put(OutItrT next, |
256 | std::ios_base& a_ios, |
257 | char_type fill_char, |
258 | const partial_date_type& pd) const |
259 | { |
260 | return m_date_gen_formatter.put_partial_date(next, a_ios, fill_char, pd, *this); |
261 | } |
262 | |
263 | OutItrT put(OutItrT next, |
264 | std::ios_base& a_ios, |
265 | char_type fill_char, |
266 | const nth_kday_type& nkd) const |
267 | { |
268 | return m_date_gen_formatter.put_nth_kday(next, a_ios, fill_char, nkd, *this); |
269 | } |
270 | |
271 | OutItrT put(OutItrT next, |
272 | std::ios_base& a_ios, |
273 | char_type fill_char, |
274 | const first_kday_type& fkd) const |
275 | { |
276 | return m_date_gen_formatter.put_first_kday(next, a_ios, fill_char, fkd, *this); |
277 | } |
278 | |
279 | OutItrT put(OutItrT next, |
280 | std::ios_base& a_ios, |
281 | char_type fill_char, |
282 | const last_kday_type& lkd) const |
283 | { |
284 | return m_date_gen_formatter.put_last_kday(next, a_ios, fill_char, lkd, *this); |
285 | } |
286 | |
287 | OutItrT put(OutItrT next, |
288 | std::ios_base& a_ios, |
289 | char_type fill_char, |
290 | const kday_before_type& fkb) const |
291 | { |
292 | return m_date_gen_formatter.put_kday_before(next, a_ios, fill_char, fkb, *this); |
293 | } |
294 | |
295 | OutItrT put(OutItrT next, |
296 | std::ios_base& a_ios, |
297 | char_type fill_char, |
298 | const kday_after_type& fka) const |
299 | { |
300 | return m_date_gen_formatter.put_kday_after(next, a_ios, fill_char, fka, *this); |
301 | } |
302 | |
303 | protected: |
304 | virtual OutItrT do_put_special(OutItrT next, |
305 | std::ios_base& /*a_ios*/, |
306 | char_type /*fill_char*/, |
307 | const boost::date_time::special_values sv) const |
308 | { |
309 | m_special_values_formatter.put_special(next, sv); |
310 | return next; |
311 | } |
312 | virtual OutItrT do_put_tm(OutItrT next, |
313 | std::ios_base& a_ios, |
314 | char_type fill_char, |
315 | const tm& tm_value, |
316 | string_type a_format) const |
317 | { |
318 | // update format string with custom names |
319 | if (!m_weekday_long_names.empty()) { |
320 | boost::algorithm::replace_all(a_format, |
321 | long_weekday_format, |
322 | m_weekday_long_names[tm_value.tm_wday]); |
323 | } |
324 | if (!m_weekday_short_names.empty()) { |
325 | boost::algorithm::replace_all(a_format, |
326 | short_weekday_format, |
327 | m_weekday_short_names[tm_value.tm_wday]); |
328 | |
329 | } |
330 | if (!m_month_long_names.empty()) { |
331 | boost::algorithm::replace_all(a_format, |
332 | long_month_format, |
333 | m_month_long_names[tm_value.tm_mon]); |
334 | } |
335 | if (!m_month_short_names.empty()) { |
336 | boost::algorithm::replace_all(a_format, |
337 | short_month_format, |
338 | m_month_short_names[tm_value.tm_mon]); |
339 | } |
340 | // use time_put facet to create final string |
341 | const char_type* p_format = a_format.c_str(); |
342 | return std::use_facet<std::time_put<CharT> >(a_ios.getloc()).put(next, a_ios, |
343 | fill_char, |
344 | &tm_value, |
345 | p_format, |
346 | p_format + a_format.size()); |
347 | } |
348 | protected: |
349 | string_type m_format; |
350 | string_type m_month_format; |
351 | string_type m_weekday_format; |
352 | period_formatter_type m_period_formatter; |
353 | date_gen_formatter_type m_date_gen_formatter; |
354 | special_values_formatter_type m_special_values_formatter; |
355 | input_collection_type m_month_short_names; |
356 | input_collection_type m_month_long_names; |
357 | input_collection_type m_weekday_short_names; |
358 | input_collection_type m_weekday_long_names; |
359 | private: |
360 | }; |
361 | |
362 | template <class date_type, class CharT, class OutItrT> |
363 | std::locale::id date_facet<date_type, CharT, OutItrT>::id; |
364 | |
365 | template <class date_type, class CharT, class OutItrT> |
366 | const typename date_facet<date_type, CharT, OutItrT>::char_type |
367 | date_facet<date_type, CharT, OutItrT>::long_weekday_format[3] = {'%','A'}; |
368 | |
369 | template <class date_type, class CharT, class OutItrT> |
370 | const typename date_facet<date_type, CharT, OutItrT>::char_type |
371 | date_facet<date_type, CharT, OutItrT>::short_weekday_format[3] = {'%','a'}; |
372 | |
373 | template <class date_type, class CharT, class OutItrT> |
374 | const typename date_facet<date_type, CharT, OutItrT>::char_type |
375 | date_facet<date_type, CharT, OutItrT>::long_month_format[3] = {'%','B'}; |
376 | |
377 | template <class date_type, class CharT, class OutItrT> |
378 | const typename date_facet<date_type, CharT, OutItrT>::char_type |
379 | date_facet<date_type, CharT, OutItrT>::short_month_format[3] = {'%','b'}; |
380 | |
381 | template <class date_type, class CharT, class OutItrT> |
382 | const typename date_facet<date_type, CharT, OutItrT>::char_type |
383 | date_facet<date_type, CharT, OutItrT>::default_period_separator[4] = { ' ', '/', ' '}; |
384 | |
385 | template <class date_type, class CharT, class OutItrT> |
386 | const typename date_facet<date_type, CharT, OutItrT>::char_type |
387 | date_facet<date_type, CharT, OutItrT>::standard_format_specifier[3] = |
388 | {'%', 'x' }; |
389 | |
390 | template <class date_type, class CharT, class OutItrT> |
391 | const typename date_facet<date_type, CharT, OutItrT>::char_type |
392 | date_facet<date_type, CharT, OutItrT>::iso_format_specifier[7] = |
393 | {'%', 'Y', '%', 'm', '%', 'd' }; |
394 | |
395 | template <class date_type, class CharT, class OutItrT> |
396 | const typename date_facet<date_type, CharT, OutItrT>::char_type |
397 | date_facet<date_type, CharT, OutItrT>::iso_format_extended_specifier[9] = |
398 | {'%', 'Y', '-', '%', 'm', '-', '%', 'd' }; |
399 | |
400 | template <class date_type, class CharT, class OutItrT> |
401 | const typename date_facet<date_type, CharT, OutItrT>::char_type |
402 | date_facet<date_type, CharT, OutItrT>::default_date_format[9] = |
403 | {'%','Y','-','%','b','-','%','d'}; |
404 | |
405 | |
406 | |
407 | //! Input facet |
408 | template <class date_type, |
409 | class CharT, |
410 | class InItrT = std::istreambuf_iterator<CharT, std::char_traits<CharT> > > |
411 | class BOOST_SYMBOL_VISIBLE date_input_facet : public std::locale::facet { |
412 | public: |
413 | typedef typename date_type::duration_type duration_type; |
414 | // greg_weekday is gregorian_calendar::day_of_week_type |
415 | typedef typename date_type::day_of_week_type day_of_week_type; |
416 | typedef typename date_type::day_type day_type; |
417 | typedef typename date_type::month_type month_type; |
418 | typedef typename date_type::year_type year_type; |
419 | typedef boost::date_time::period<date_type,duration_type> period_type; |
420 | typedef std::basic_string<CharT> string_type; |
421 | typedef CharT char_type; |
422 | typedef boost::date_time::period_parser<date_type, CharT> period_parser_type; |
423 | typedef boost::date_time::special_values_parser<date_type,CharT> special_values_parser_type; |
424 | typedef std::vector<std::basic_string<CharT> > input_collection_type; |
425 | typedef format_date_parser<date_type, CharT> format_date_parser_type; |
426 | // date_generators stuff goes here |
427 | typedef date_generator_parser<date_type, CharT> date_gen_parser_type; |
428 | typedef partial_date<date_type> partial_date_type; |
429 | typedef nth_kday_of_month<date_type> nth_kday_type; |
430 | typedef first_kday_of_month<date_type> first_kday_type; |
431 | typedef last_kday_of_month<date_type> last_kday_type; |
432 | typedef first_kday_after<date_type> kday_after_type; |
433 | typedef first_kday_before<date_type> kday_before_type; |
434 | |
435 | static const char_type long_weekday_format[3]; |
436 | static const char_type short_weekday_format[3]; |
437 | static const char_type long_month_format[3]; |
438 | static const char_type short_month_format[3]; |
439 | static const char_type four_digit_year_format[3]; |
440 | static const char_type two_digit_year_format[3]; |
441 | static const char_type default_period_separator[4]; |
442 | static const char_type standard_format_specifier[3]; |
443 | static const char_type iso_format_specifier[7]; |
444 | static const char_type iso_format_extended_specifier[9]; |
445 | static const char_type default_date_format[9]; // YYYY-Mon-DD |
446 | static std::locale::id id; |
447 | |
448 | explicit date_input_facet(::size_t a_ref = 0) |
449 | : std::locale::facet(a_ref), |
450 | m_format(default_date_format), |
451 | m_month_format(short_month_format), |
452 | m_weekday_format(short_weekday_format), |
453 | m_year_format(four_digit_year_format), |
454 | m_parser(m_format, std::locale::classic()) |
455 | // default period_parser & special_values_parser used |
456 | {} |
457 | |
458 | explicit date_input_facet(const string_type& format_str, |
459 | ::size_t a_ref = 0) |
460 | : std::locale::facet(a_ref), |
461 | m_format(format_str), |
462 | m_month_format(short_month_format), |
463 | m_weekday_format(short_weekday_format), |
464 | m_year_format(four_digit_year_format), |
465 | m_parser(m_format, std::locale::classic()) |
466 | // default period_parser & special_values_parser used |
467 | {} |
468 | |
469 | explicit date_input_facet(const string_type& format_str, |
470 | const format_date_parser_type& date_parser, |
471 | const special_values_parser_type& sv_parser, |
472 | const period_parser_type& per_parser, |
473 | const date_gen_parser_type& date_gen_parser, |
474 | ::size_t ref_count = 0) |
475 | : std::locale::facet(ref_count), |
476 | m_format(format_str), |
477 | m_month_format(short_month_format), |
478 | m_weekday_format(short_weekday_format), |
479 | m_year_format(four_digit_year_format), |
480 | m_parser(date_parser), |
481 | m_date_gen_parser(date_gen_parser), |
482 | m_period_parser(per_parser), |
483 | m_sv_parser(sv_parser) |
484 | {} |
485 | |
486 | |
487 | void format(const char_type* const format_str) { |
488 | m_format = format_str; |
489 | } |
490 | virtual void set_iso_format() |
491 | { |
492 | m_format = iso_format_specifier; |
493 | } |
494 | virtual void set_iso_extended_format() |
495 | { |
496 | m_format = iso_format_extended_specifier; |
497 | } |
498 | void month_format(const char_type* const format_str) { |
499 | m_month_format = format_str; |
500 | } |
501 | void weekday_format(const char_type* const format_str) { |
502 | m_weekday_format = format_str; |
503 | } |
504 | void year_format(const char_type* const format_str) { |
505 | m_year_format = format_str; |
506 | } |
507 | |
508 | void period_parser(period_parser_type per_parser) { |
509 | m_period_parser = per_parser; |
510 | } |
511 | void short_weekday_names(const input_collection_type& weekday_names) |
512 | { |
513 | m_parser.short_weekday_names(weekday_names); |
514 | } |
515 | void long_weekday_names(const input_collection_type& weekday_names) |
516 | { |
517 | m_parser.long_weekday_names(weekday_names); |
518 | } |
519 | |
520 | void short_month_names(const input_collection_type& month_names) |
521 | { |
522 | m_parser.short_month_names(month_names); |
523 | } |
524 | |
525 | void long_month_names(const input_collection_type& month_names) |
526 | { |
527 | m_parser.long_month_names(month_names); |
528 | } |
529 | |
530 | void date_gen_element_strings(const input_collection_type& col) |
531 | { |
532 | m_date_gen_parser.element_strings(col); |
533 | } |
534 | void date_gen_element_strings(const string_type& first, |
535 | const string_type& second, |
536 | const string_type& third, |
537 | const string_type& fourth, |
538 | const string_type& fifth, |
539 | const string_type& last, |
540 | const string_type& before, |
541 | const string_type& after, |
542 | const string_type& of) |
543 | |
544 | { |
545 | m_date_gen_parser.element_strings(first,second,third,fourth,fifth,last,before,after,of); |
546 | } |
547 | |
548 | void special_values_parser(special_values_parser_type sv_parser) |
549 | { |
550 | m_sv_parser = sv_parser; |
551 | } |
552 | |
553 | InItrT get(InItrT& from, |
554 | InItrT& to, |
555 | std::ios_base& /*a_ios*/, |
556 | date_type& d) const |
557 | { |
558 | d = m_parser.parse_date(from, to, m_format, m_sv_parser); |
559 | return from; |
560 | } |
561 | InItrT get(InItrT& from, |
562 | InItrT& to, |
563 | std::ios_base& /*a_ios*/, |
564 | month_type& m) const |
565 | { |
566 | m = m_parser.parse_month(from, to, m_month_format); |
567 | return from; |
568 | } |
569 | InItrT get(InItrT& from, |
570 | InItrT& to, |
571 | std::ios_base& /*a_ios*/, |
572 | day_of_week_type& wd) const |
573 | { |
574 | wd = m_parser.parse_weekday(from, to, m_weekday_format); |
575 | return from; |
576 | } |
577 | //! Expects 1 or 2 digit day range: 1-31 |
578 | InItrT get(InItrT& from, |
579 | InItrT& to, |
580 | std::ios_base& /*a_ios*/, |
581 | day_type& d) const |
582 | { |
583 | d = m_parser.parse_var_day_of_month(from, to); |
584 | return from; |
585 | } |
586 | InItrT get(InItrT& from, |
587 | InItrT& to, |
588 | std::ios_base& /*a_ios*/, |
589 | year_type& y) const |
590 | { |
591 | y = m_parser.parse_year(from, to, m_year_format); |
592 | return from; |
593 | } |
594 | InItrT get(InItrT& from, |
595 | InItrT& to, |
596 | std::ios_base& a_ios, |
597 | duration_type& dd) const |
598 | { |
599 | // skip leading whitespace |
600 | while(std::isspace(*from) && from != to) { ++from; } |
601 | |
602 | /* num_get.get() will always consume the first character if it |
603 | * is a sign indicator (+/-). Special value strings may begin |
604 | * with one of these signs so we'll need a copy of it |
605 | * in case num_get.get() fails. */ |
606 | char_type c = '\0'; |
607 | // TODO Are these characters somewhere in the locale? |
608 | if(*from == '-' || *from == '+') { |
609 | c = *from; |
610 | } |
611 | typedef std::num_get<CharT, InItrT> num_get; |
612 | typename duration_type::duration_rep_type val = 0; |
613 | std::ios_base::iostate err = std::ios_base::goodbit; |
614 | |
615 | if (std::has_facet<num_get>(a_ios.getloc())) { |
616 | from = std::use_facet<num_get>(a_ios.getloc()).get(from, to, a_ios, err, val); |
617 | } |
618 | else { |
619 | num_get* ng = new num_get(); |
620 | std::locale l = std::locale(a_ios.getloc(), ng); |
621 | a_ios.imbue(loc: l); |
622 | from = ng->get(from, to, a_ios, err, val); |
623 | } |
624 | if(err & std::ios_base::failbit){ |
625 | typedef typename special_values_parser_type::match_results match_results; |
626 | match_results mr; |
627 | if(c == '-' || c == '+') { // was the first character consumed? |
628 | mr.cache += c; |
629 | } |
630 | m_sv_parser.match(from, to, mr); |
631 | if(mr.current_match == match_results::PARSE_ERROR) { |
632 | boost::throw_exception(e: std::ios_base::failure("Parse failed. No match found for '" + mr.cache + "'" )); |
633 | BOOST_DATE_TIME_UNREACHABLE_EXPRESSION(return from); // should never reach |
634 | } |
635 | dd = duration_type(static_cast<special_values>(mr.current_match)); |
636 | } |
637 | else { |
638 | dd = duration_type(val); |
639 | } |
640 | return from; |
641 | } |
642 | InItrT get(InItrT& from, |
643 | InItrT& to, |
644 | std::ios_base& a_ios, |
645 | period_type& p) const |
646 | { |
647 | p = m_period_parser.get_period(from, to, a_ios, p, duration_type::unit(), *this); |
648 | return from; |
649 | } |
650 | InItrT get(InItrT& from, |
651 | InItrT& to, |
652 | std::ios_base& a_ios, |
653 | nth_kday_type& nkd) const |
654 | { |
655 | nkd = m_date_gen_parser.get_nth_kday_type(from, to, a_ios, *this); |
656 | return from; |
657 | } |
658 | InItrT get(InItrT& from, |
659 | InItrT& to, |
660 | std::ios_base& a_ios, |
661 | partial_date_type& pd) const |
662 | { |
663 | |
664 | pd = m_date_gen_parser.get_partial_date_type(from, to, a_ios, *this); |
665 | return from; |
666 | } |
667 | InItrT get(InItrT& from, |
668 | InItrT& to, |
669 | std::ios_base& a_ios, |
670 | first_kday_type& fkd) const |
671 | { |
672 | fkd = m_date_gen_parser.get_first_kday_type(from, to, a_ios, *this); |
673 | return from; |
674 | } |
675 | InItrT get(InItrT& from, |
676 | InItrT& to, |
677 | std::ios_base& a_ios, |
678 | last_kday_type& lkd) const |
679 | { |
680 | lkd = m_date_gen_parser.get_last_kday_type(from, to, a_ios, *this); |
681 | return from; |
682 | } |
683 | InItrT get(InItrT& from, |
684 | InItrT& to, |
685 | std::ios_base& a_ios, |
686 | kday_before_type& fkb) const |
687 | { |
688 | fkb = m_date_gen_parser.get_kday_before_type(from, to, a_ios, *this); |
689 | return from; |
690 | } |
691 | InItrT get(InItrT& from, |
692 | InItrT& to, |
693 | std::ios_base& a_ios, |
694 | kday_after_type& fka) const |
695 | { |
696 | fka = m_date_gen_parser.get_kday_after_type(from, to, a_ios, *this); |
697 | return from; |
698 | } |
699 | |
700 | protected: |
701 | string_type m_format; |
702 | string_type m_month_format; |
703 | string_type m_weekday_format; |
704 | string_type m_year_format; |
705 | format_date_parser_type m_parser; |
706 | date_gen_parser_type m_date_gen_parser; |
707 | period_parser_type m_period_parser; |
708 | special_values_parser_type m_sv_parser; |
709 | private: |
710 | }; |
711 | |
712 | |
713 | template <class date_type, class CharT, class OutItrT> |
714 | std::locale::id date_input_facet<date_type, CharT, OutItrT>::id; |
715 | |
716 | template <class date_type, class CharT, class OutItrT> |
717 | const typename date_input_facet<date_type, CharT, OutItrT>::char_type |
718 | date_input_facet<date_type, CharT, OutItrT>::long_weekday_format[3] = {'%','A'}; |
719 | |
720 | template <class date_type, class CharT, class OutItrT> |
721 | const typename date_input_facet<date_type, CharT, OutItrT>::char_type |
722 | date_input_facet<date_type, CharT, OutItrT>::short_weekday_format[3] = {'%','a'}; |
723 | |
724 | template <class date_type, class CharT, class OutItrT> |
725 | const typename date_input_facet<date_type, CharT, OutItrT>::char_type |
726 | date_input_facet<date_type, CharT, OutItrT>::long_month_format[3] = {'%','B'}; |
727 | |
728 | template <class date_type, class CharT, class OutItrT> |
729 | const typename date_input_facet<date_type, CharT, OutItrT>::char_type |
730 | date_input_facet<date_type, CharT, OutItrT>::short_month_format[3] = {'%','b'}; |
731 | |
732 | template <class date_type, class CharT, class OutItrT> |
733 | const typename date_input_facet<date_type, CharT, OutItrT>::char_type |
734 | date_input_facet<date_type, CharT, OutItrT>::four_digit_year_format[3] = {'%','Y'}; |
735 | |
736 | template <class date_type, class CharT, class OutItrT> |
737 | const typename date_input_facet<date_type, CharT, OutItrT>::char_type |
738 | date_input_facet<date_type, CharT, OutItrT>::two_digit_year_format[3] = {'%','y'}; |
739 | |
740 | template <class date_type, class CharT, class OutItrT> |
741 | const typename date_input_facet<date_type, CharT, OutItrT>::char_type |
742 | date_input_facet<date_type, CharT, OutItrT>::default_period_separator[4] = { ' ', '/', ' '}; |
743 | |
744 | template <class date_type, class CharT, class OutItrT> |
745 | const typename date_input_facet<date_type, CharT, OutItrT>::char_type |
746 | date_input_facet<date_type, CharT, OutItrT>::standard_format_specifier[3] = |
747 | {'%', 'x' }; |
748 | |
749 | template <class date_type, class CharT, class OutItrT> |
750 | const typename date_input_facet<date_type, CharT, OutItrT>::char_type |
751 | date_input_facet<date_type, CharT, OutItrT>::iso_format_specifier[7] = |
752 | {'%', 'Y', '%', 'm', '%', 'd' }; |
753 | |
754 | template <class date_type, class CharT, class OutItrT> |
755 | const typename date_input_facet<date_type, CharT, OutItrT>::char_type |
756 | date_input_facet<date_type, CharT, OutItrT>::iso_format_extended_specifier[9] = |
757 | {'%', 'Y', '-', '%', 'm', '-', '%', 'd' }; |
758 | |
759 | template <class date_type, class CharT, class OutItrT> |
760 | const typename date_input_facet<date_type, CharT, OutItrT>::char_type |
761 | date_input_facet<date_type, CharT, OutItrT>::default_date_format[9] = |
762 | {'%','Y','-','%','b','-','%','d'}; |
763 | |
764 | } } // namespaces |
765 | |
766 | #endif |
767 | |