annotate DEPENDENCIES/generic/include/boost/date_time/time_facet.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
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