annotate DEPENDENCIES/generic/include/boost/date_time/date_facet.hpp @ 125:34e428693f5d vext

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