Chris@16: Chris@16: #ifndef _DATE_TIME_FACET__HPP__ Chris@16: #define _DATE_TIME_FACET__HPP__ Chris@16: Chris@16: /* Copyright (c) 2004-2005 CrystalClear Software, Inc. Chris@16: * Use, modification and distribution is subject to the Chris@16: * Boost Software License, Version 1.0. (See accompanying Chris@16: * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) Chris@16: * Author: Martin Andrian, Jeff Garland, Bart Garst Chris@101: * $Date$ Chris@16: */ Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include // i/ostreambuf_iterator Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include // absolute_value Chris@16: Chris@16: namespace boost { Chris@16: namespace date_time { Chris@16: Chris@16: template Chris@16: struct time_formats { Chris@16: public: Chris@16: typedef CharT char_type; Chris@16: static const char_type fractional_seconds_format[3]; // f Chris@16: static const char_type fractional_seconds_or_none_format[3]; // F Chris@16: static const char_type seconds_with_fractional_seconds_format[3]; // s Chris@16: static const char_type seconds_format[3]; // S Chris@16: static const char_type hours_format[3]; // H Chris@16: static const char_type unrestricted_hours_format[3]; // O Chris@16: static const char_type full_24_hour_time_format[3]; // T Chris@16: static const char_type full_24_hour_time_expanded_format[9]; // HH:MM:SS Chris@16: static const char_type short_24_hour_time_format[3]; // R Chris@16: static const char_type short_24_hour_time_expanded_format[6]; // HH:MM Chris@16: static const char_type standard_format[9]; // x X Chris@16: static const char_type zone_abbrev_format[3]; // z Chris@16: static const char_type zone_name_format[3]; // Z Chris@16: static const char_type zone_iso_format[3]; // q Chris@16: static const char_type zone_iso_extended_format[3]; // Q Chris@16: static const char_type posix_zone_string_format[4]; // ZP Chris@16: static const char_type duration_sign_negative_only[3]; // - Chris@16: static const char_type duration_sign_always[3]; // + Chris@16: static const char_type duration_seperator[2]; Chris@16: static const char_type negative_sign[2]; //- Chris@16: static const char_type positive_sign[2]; //+ Chris@16: static const char_type iso_time_format_specifier[18]; Chris@16: static const char_type iso_time_format_extended_specifier[22]; Chris@16: //default ptime format is YYYY-Mon-DD HH:MM:SS[.fff...][ zzz] Chris@16: static const char_type default_time_format[23]; Chris@16: // default_time_input_format uses a posix_time_zone_string instead of a time zone abbrev Chris@16: static const char_type default_time_input_format[24]; Chris@16: //default time_duration format is HH:MM:SS[.fff...] Chris@16: static const char_type default_time_duration_format[11]; Chris@16: }; Chris@16: Chris@16: template Chris@16: const typename time_formats::char_type Chris@16: time_formats::fractional_seconds_format[3] = {'%','f'}; Chris@16: Chris@16: template Chris@16: const typename time_formats::char_type Chris@16: time_formats::fractional_seconds_or_none_format[3] = {'%','F'}; Chris@16: Chris@16: template Chris@16: const typename time_formats::char_type Chris@16: time_formats::seconds_with_fractional_seconds_format[3] = {'%','s'}; Chris@16: Chris@16: template Chris@16: const typename time_formats::char_type Chris@16: time_formats::seconds_format[3] = {'%','S'}; Chris@16: Chris@16: template Chris@16: const typename time_formats::char_type Chris@16: time_formats::hours_format[3] = {'%','H'}; Chris@16: Chris@16: template Chris@16: const typename time_formats::char_type Chris@16: time_formats::unrestricted_hours_format[3] = {'%','O'}; Chris@16: Chris@16: template Chris@16: const typename time_formats::char_type Chris@16: time_formats::full_24_hour_time_format[3] = {'%','T'}; Chris@16: Chris@16: template Chris@16: const typename time_formats::char_type Chris@16: time_formats::full_24_hour_time_expanded_format[9] = Chris@16: {'%','H',':','%','M',':','%','S'}; Chris@16: Chris@16: template Chris@16: const typename time_formats::char_type Chris@16: time_formats::short_24_hour_time_format[3] = {'%','R'}; Chris@16: Chris@16: template Chris@16: const typename time_formats::char_type Chris@16: time_formats::short_24_hour_time_expanded_format[6] = Chris@16: {'%','H',':','%','M'}; Chris@16: Chris@16: template Chris@16: const typename time_formats::char_type Chris@16: //time_formats::standard_format[5] = {'%','c',' ','%','z'}; Chris@16: time_formats::standard_format[9] = {'%','x',' ','%','X',' ','%','z'}; Chris@16: Chris@16: template Chris@16: const typename time_formats::char_type Chris@16: time_formats::zone_abbrev_format[3] = {'%','z'}; Chris@16: Chris@16: template Chris@16: const typename time_formats::char_type Chris@16: time_formats::zone_name_format[3] = {'%','Z'}; Chris@16: Chris@16: template Chris@16: const typename time_formats::char_type Chris@16: time_formats::zone_iso_format[3] = {'%','q'}; Chris@16: Chris@16: template Chris@16: const typename time_formats::char_type Chris@16: time_formats::zone_iso_extended_format[3] ={'%','Q'}; Chris@16: Chris@16: template Chris@16: const typename time_formats::char_type Chris@16: time_formats::posix_zone_string_format[4] ={'%','Z','P'}; Chris@16: Chris@16: template Chris@16: const typename time_formats::char_type Chris@16: time_formats::duration_seperator[2] = {':'}; Chris@16: Chris@16: template Chris@16: const typename time_formats::char_type Chris@16: time_formats::negative_sign[2] = {'-'}; Chris@16: Chris@16: template Chris@16: const typename time_formats::char_type Chris@16: time_formats::positive_sign[2] = {'+'}; Chris@16: Chris@16: template Chris@16: const typename time_formats::char_type Chris@16: time_formats::duration_sign_negative_only[3] ={'%','-'}; Chris@16: Chris@16: template Chris@16: const typename time_formats::char_type Chris@16: time_formats::duration_sign_always[3] ={'%','+'}; Chris@16: Chris@16: template Chris@16: const typename time_formats::char_type Chris@16: time_formats::iso_time_format_specifier[18] = Chris@16: {'%', 'Y', '%', 'm', '%', 'd', 'T', Chris@16: '%', 'H', '%', 'M', '%', 'S', '%', 'F', '%','q' }; Chris@16: Chris@16: template Chris@16: const typename time_formats::char_type Chris@16: time_formats::iso_time_format_extended_specifier[22] = Chris@16: {'%', 'Y', '-', '%', 'm', '-', '%', 'd', ' ', Chris@16: '%', 'H', ':', '%', 'M', ':', '%', 'S', '%', 'F','%','Q'}; Chris@16: Chris@16: template Chris@16: const typename time_formats::char_type Chris@16: time_formats::default_time_format[23] = Chris@16: {'%','Y','-','%','b','-','%','d',' ', Chris@16: '%','H',':','%','M',':','%','S','%','F',' ','%','z'}; Chris@16: Chris@16: template Chris@16: const typename time_formats::char_type Chris@16: time_formats::default_time_input_format[24] = Chris@16: {'%','Y','-','%','b','-','%','d',' ', Chris@16: '%','H',':','%','M',':','%','S','%','F',' ','%','Z','P'}; Chris@16: Chris@16: template Chris@16: const typename time_formats::char_type Chris@16: time_formats::default_time_duration_format[11] = Chris@16: {'%','O',':','%','M',':','%','S','%','F'}; Chris@16: Chris@16: Chris@16: Chris@16: /*! Facet used for format-based output of time types Chris@16: * This class provides for the use of format strings to output times. In addition Chris@16: * to the flags for formatting date elements, the following are the allowed format flags: Chris@16: * - %x %X => default format - enables addition of more flags to default (ie. "%x %X %z") Chris@16: * - %f => fractional seconds ".123456" Chris@16: * - %F => fractional seconds or none: like frac sec but empty if frac sec == 0 Chris@16: * - %s => seconds w/ fractional sec "02.123" (this is the same as "%S%f) Chris@16: * - %S => seconds "02" Chris@16: * - %z => abbreviated time zone "EDT" Chris@16: * - %Z => full time zone name "Eastern Daylight Time" Chris@16: */ Chris@16: template > > Chris@16: class time_facet : Chris@16: public boost::date_time::date_facet { Chris@16: typedef time_formats< CharT > formats_type; Chris@16: public: Chris@16: typedef typename time_type::date_type date_type; Chris@16: typedef typename time_type::time_duration_type time_duration_type; Chris@16: typedef boost::date_time::period period_type; Chris@16: typedef boost::date_time::date_facet base_type; Chris@16: typedef typename base_type::string_type string_type; Chris@16: typedef typename base_type::char_type char_type; Chris@16: typedef typename base_type::period_formatter_type period_formatter_type; Chris@16: typedef typename base_type::special_values_formatter_type special_values_formatter_type; Chris@16: typedef typename base_type::date_gen_formatter_type date_gen_formatter_type; Chris@16: static const char_type* fractional_seconds_format; // %f Chris@16: static const char_type* fractional_seconds_or_none_format; // %F Chris@16: static const char_type* seconds_with_fractional_seconds_format; // %s Chris@16: static const char_type* seconds_format; // %S Chris@16: static const char_type* hours_format; // %H Chris@16: static const char_type* unrestricted_hours_format; // %O Chris@16: static const char_type* standard_format; // %x X Chris@16: static const char_type* zone_abbrev_format; // %z Chris@16: static const char_type* zone_name_format; // %Z Chris@16: static const char_type* zone_iso_format; // %q Chris@16: static const char_type* zone_iso_extended_format; // %Q Chris@16: static const char_type* posix_zone_string_format; // %ZP Chris@16: static const char_type* duration_seperator; Chris@16: static const char_type* duration_sign_always; // %+ Chris@16: static const char_type* duration_sign_negative_only; // %- Chris@16: static const char_type* negative_sign; //- Chris@16: static const char_type* positive_sign; //+ Chris@16: static const char_type* iso_time_format_specifier; Chris@16: static const char_type* iso_time_format_extended_specifier; Chris@16: Chris@16: //default ptime format is YYYY-Mon-DD HH:MM:SS[.fff...][ zzz] Chris@16: static const char_type* default_time_format; Chris@16: //default time_duration format is HH:MM:SS[.fff...] Chris@16: static const char_type* default_time_duration_format; Chris@16: static std::locale::id id; Chris@16: Chris@16: #if defined (__SUNPRO_CC) && defined (_RWSTD_VER) Chris@16: std::locale::id& __get_id (void) const { return id; } Chris@16: #endif Chris@16: Chris@16: //! sets default formats for ptime, local_date_time, and time_duration Chris@16: explicit time_facet(::size_t ref_arg = 0) Chris@16: : base_type(default_time_format, period_formatter_type(), special_values_formatter_type(), date_gen_formatter_type(), ref_arg), Chris@16: m_time_duration_format(string_type(duration_sign_negative_only) + default_time_duration_format) Chris@16: {} Chris@16: Chris@16: //! Construct the facet with an explicitly specified format Chris@16: explicit time_facet(const char_type* format_arg, Chris@16: period_formatter_type period_formatter_arg = period_formatter_type(), Chris@16: const special_values_formatter_type& special_value_formatter = special_values_formatter_type(), Chris@16: date_gen_formatter_type dg_formatter = date_gen_formatter_type(), Chris@16: ::size_t ref_arg = 0) Chris@16: : base_type(format_arg, Chris@16: period_formatter_arg, Chris@16: special_value_formatter, Chris@16: dg_formatter, Chris@16: ref_arg), Chris@16: m_time_duration_format(string_type(duration_sign_negative_only) + default_time_duration_format) Chris@16: {} Chris@16: Chris@16: //! Changes format for time_duration Chris@16: void time_duration_format(const char_type* const format) Chris@16: { Chris@16: m_time_duration_format = format; Chris@16: } Chris@16: Chris@16: virtual void set_iso_format() Chris@16: { Chris@16: this->m_format = iso_time_format_specifier; Chris@16: } Chris@16: virtual void set_iso_extended_format() Chris@16: { Chris@16: this->m_format = iso_time_format_extended_specifier; Chris@16: } Chris@16: Chris@16: OutItrT put(OutItrT next_arg, Chris@16: std::ios_base& ios_arg, Chris@16: char_type fill_arg, Chris@16: const time_type& time_arg) const Chris@16: { Chris@16: if (time_arg.is_special()) { Chris@16: return this->do_put_special(next_arg, ios_arg, fill_arg, Chris@16: time_arg.date().as_special()); Chris@16: } Chris@16: string_type local_format(this->m_format); Chris@16: Chris@16: // %T and %R have to be replaced here since they are not standard Chris@16: boost::algorithm::replace_all(local_format, Chris@16: boost::as_literal(formats_type::full_24_hour_time_format), Chris@16: boost::as_literal(formats_type::full_24_hour_time_expanded_format)); Chris@16: boost::algorithm::replace_all(local_format, Chris@16: boost::as_literal(formats_type::short_24_hour_time_format), Chris@16: boost::as_literal(formats_type::short_24_hour_time_expanded_format)); Chris@16: Chris@16: string_type frac_str; Chris@16: if (local_format.find(seconds_with_fractional_seconds_format) != string_type::npos) { Chris@16: // replace %s with %S.nnn Chris@16: frac_str = Chris@16: fractional_seconds_as_string(time_arg.time_of_day(), false); Chris@16: char_type sep = std::use_facet >(ios_arg.getloc()).decimal_point(); Chris@16: Chris@16: string_type replace_string(seconds_format); Chris@16: replace_string += sep; Chris@16: replace_string += frac_str; Chris@16: boost::algorithm::replace_all(local_format, Chris@16: seconds_with_fractional_seconds_format, Chris@16: replace_string); Chris@16: } Chris@16: /* NOTE: replacing posix_zone_string_format must be done BEFORE Chris@16: * zone_name_format: "%ZP" & "%Z", if Z is checked first it will Chris@16: * incorrectly replace a zone_name where a posix_string should go */ Chris@16: if (local_format.find(posix_zone_string_format) != string_type::npos) { Chris@16: if(time_arg.zone_abbrev().empty()) { Chris@16: // if zone_abbrev() returns an empty string, we want to Chris@16: // erase posix_zone_string_format from format Chris@16: boost::algorithm::erase_all(local_format, posix_zone_string_format); Chris@16: } Chris@16: else{ Chris@16: boost::algorithm::replace_all(local_format, Chris@16: posix_zone_string_format, Chris@16: time_arg.zone_as_posix_string()); Chris@16: } Chris@16: } Chris@16: if (local_format.find(zone_name_format) != string_type::npos) { Chris@16: if(time_arg.zone_name().empty()) { Chris@16: /* TODO: this'll probably create problems if a user places Chris@16: * the zone_*_format flag in the format with a ptime. This Chris@16: * code removes the flag from the default formats */ Chris@16: Chris@16: // if zone_name() returns an empty string, we want to Chris@16: // erase zone_name_format & one preceeding space Chris@16: std::basic_ostringstream ss; Chris@16: ss << ' ' << zone_name_format; Chris@16: boost::algorithm::erase_all(local_format, ss.str()); Chris@16: } Chris@16: else{ Chris@16: boost::algorithm::replace_all(local_format, Chris@16: zone_name_format, Chris@16: time_arg.zone_name()); Chris@16: } Chris@16: } Chris@16: if (local_format.find(zone_abbrev_format) != string_type::npos) { Chris@16: if(time_arg.zone_abbrev(false).empty()) { Chris@16: /* TODO: this'll probably create problems if a user places Chris@16: * the zone_*_format flag in the format with a ptime. This Chris@16: * code removes the flag from the default formats */ Chris@16: Chris@16: // if zone_abbrev() returns an empty string, we want to Chris@16: // erase zone_abbrev_format & one preceeding space Chris@16: std::basic_ostringstream ss; Chris@16: ss << ' ' << zone_abbrev_format; Chris@16: boost::algorithm::erase_all(local_format, ss.str()); Chris@16: } Chris@16: else{ Chris@16: boost::algorithm::replace_all(local_format, Chris@16: zone_abbrev_format, Chris@16: time_arg.zone_abbrev(false)); Chris@16: } Chris@16: } Chris@16: if (local_format.find(zone_iso_extended_format) != string_type::npos) { Chris@16: if(time_arg.zone_name(true).empty()) { Chris@16: /* TODO: this'll probably create problems if a user places Chris@16: * the zone_*_format flag in the format with a ptime. This Chris@16: * code removes the flag from the default formats */ Chris@16: Chris@16: // if zone_name() returns an empty string, we want to Chris@16: // erase zone_iso_extended_format from format Chris@16: boost::algorithm::erase_all(local_format, zone_iso_extended_format); Chris@16: } Chris@16: else{ Chris@16: boost::algorithm::replace_all(local_format, Chris@16: zone_iso_extended_format, Chris@16: time_arg.zone_name(true)); Chris@16: } Chris@16: } Chris@16: Chris@16: if (local_format.find(zone_iso_format) != string_type::npos) { Chris@16: if(time_arg.zone_abbrev(true).empty()) { Chris@16: /* TODO: this'll probably create problems if a user places Chris@16: * the zone_*_format flag in the format with a ptime. This Chris@16: * code removes the flag from the default formats */ Chris@16: Chris@16: // if zone_abbrev() returns an empty string, we want to Chris@16: // erase zone_iso_format from format Chris@16: boost::algorithm::erase_all(local_format, zone_iso_format); Chris@16: } Chris@16: else{ Chris@16: boost::algorithm::replace_all(local_format, Chris@16: zone_iso_format, Chris@16: time_arg.zone_abbrev(true)); Chris@16: } Chris@16: } Chris@16: if (local_format.find(fractional_seconds_format) != string_type::npos) { Chris@16: // replace %f with nnnnnnn Chris@16: if (frac_str.empty()) { Chris@16: frac_str = fractional_seconds_as_string(time_arg.time_of_day(), false); Chris@16: } Chris@16: boost::algorithm::replace_all(local_format, Chris@16: fractional_seconds_format, Chris@16: frac_str); Chris@16: } Chris@16: Chris@16: if (local_format.find(fractional_seconds_or_none_format) != string_type::npos) { Chris@16: // replace %F with nnnnnnn or nothing if fs == 0 Chris@16: frac_str = Chris@16: fractional_seconds_as_string(time_arg.time_of_day(), true); Chris@16: if (frac_str.size()) { Chris@16: char_type sep = std::use_facet >(ios_arg.getloc()).decimal_point(); Chris@16: string_type replace_string; Chris@16: replace_string += sep; Chris@16: replace_string += frac_str; Chris@16: boost::algorithm::replace_all(local_format, Chris@16: fractional_seconds_or_none_format, Chris@16: replace_string); Chris@16: } Chris@16: else { Chris@16: boost::algorithm::erase_all(local_format, Chris@16: fractional_seconds_or_none_format); Chris@16: } Chris@16: } Chris@16: Chris@16: return this->do_put_tm(next_arg, ios_arg, fill_arg, Chris@16: to_tm(time_arg), local_format); Chris@16: } Chris@16: Chris@16: //! put function for time_duration Chris@16: OutItrT put(OutItrT next_arg, Chris@16: std::ios_base& ios_arg, Chris@16: char_type fill_arg, Chris@16: const time_duration_type& time_dur_arg) const Chris@16: { Chris@16: if (time_dur_arg.is_special()) { Chris@16: return this->do_put_special(next_arg, ios_arg, fill_arg, Chris@16: time_dur_arg.get_rep().as_special()); Chris@16: } Chris@16: Chris@16: string_type format(m_time_duration_format); Chris@16: if (time_dur_arg.is_negative()) { Chris@16: // replace %- with minus sign. Should we use the numpunct facet? Chris@16: boost::algorithm::replace_all(format, Chris@16: duration_sign_negative_only, Chris@16: negative_sign); Chris@16: // remove all the %+ in the string with '-' Chris@16: boost::algorithm::replace_all(format, Chris@16: duration_sign_always, Chris@16: negative_sign); Chris@16: } Chris@16: else { //duration is positive Chris@16: // remove all the %- combos from the string Chris@16: boost::algorithm::erase_all(format, duration_sign_negative_only); Chris@16: // remove all the %+ in the string with '+' Chris@16: boost::algorithm::replace_all(format, Chris@16: duration_sign_always, Chris@16: positive_sign); Chris@16: } Chris@16: Chris@16: // %T and %R have to be replaced here since they are not standard Chris@16: boost::algorithm::replace_all(format, Chris@16: boost::as_literal(formats_type::full_24_hour_time_format), Chris@16: boost::as_literal(formats_type::full_24_hour_time_expanded_format)); Chris@16: boost::algorithm::replace_all(format, Chris@16: boost::as_literal(formats_type::short_24_hour_time_format), Chris@16: boost::as_literal(formats_type::short_24_hour_time_expanded_format)); Chris@16: Chris@16: /* Chris@16: * It is possible for a time duration to span more then 24 hours. Chris@16: * Standard time_put::put is obliged to behave the same as strftime Chris@16: * (See ISO 14882-2003 22.2.5.3.1 par. 1) and strftime's behavior is Chris@16: * unspecified for the case when tm_hour field is outside 0-23 range Chris@16: * (See ISO 9899-1999 7.23.3.5 par. 3). So we must output %H and %O Chris@16: * here ourself. Chris@16: */ Chris@16: string_type hours_str; Chris@16: if (format.find(unrestricted_hours_format) != string_type::npos) { Chris@16: hours_str = hours_as_string(time_dur_arg); Chris@16: boost::algorithm::replace_all(format, unrestricted_hours_format, hours_str); Chris@16: } Chris@16: // We still have to process restricted hours format specifier. In order to Chris@16: // support parseability of durations in ISO format (%H%M%S), we'll have to Chris@16: // restrict the stringified hours length to 2 characters. Chris@16: if (format.find(hours_format) != string_type::npos) { Chris@16: if (hours_str.empty()) Chris@16: hours_str = hours_as_string(time_dur_arg); Chris@16: BOOST_ASSERT(hours_str.length() <= 2); Chris@16: boost::algorithm::replace_all(format, hours_format, hours_str); Chris@16: } Chris@16: Chris@16: string_type frac_str; Chris@16: if (format.find(seconds_with_fractional_seconds_format) != string_type::npos) { Chris@16: // replace %s with %S.nnn Chris@16: frac_str = Chris@16: fractional_seconds_as_string(time_dur_arg, false); Chris@16: char_type sep = std::use_facet >(ios_arg.getloc()).decimal_point(); Chris@16: Chris@16: string_type replace_string(seconds_format); Chris@16: replace_string += sep; Chris@16: replace_string += frac_str; Chris@16: boost::algorithm::replace_all(format, Chris@16: seconds_with_fractional_seconds_format, Chris@16: replace_string); Chris@16: } Chris@16: if (format.find(fractional_seconds_format) != string_type::npos) { Chris@16: // replace %f with nnnnnnn Chris@16: if (!frac_str.size()) { Chris@16: frac_str = fractional_seconds_as_string(time_dur_arg, false); Chris@16: } Chris@16: boost::algorithm::replace_all(format, Chris@16: fractional_seconds_format, Chris@16: frac_str); Chris@16: } Chris@16: Chris@16: if (format.find(fractional_seconds_or_none_format) != string_type::npos) { Chris@16: // replace %F with nnnnnnn or nothing if fs == 0 Chris@16: frac_str = Chris@16: fractional_seconds_as_string(time_dur_arg, true); Chris@16: if (frac_str.size()) { Chris@16: char_type sep = std::use_facet >(ios_arg.getloc()).decimal_point(); Chris@16: string_type replace_string; Chris@16: replace_string += sep; Chris@16: replace_string += frac_str; Chris@16: boost::algorithm::replace_all(format, Chris@16: fractional_seconds_or_none_format, Chris@16: replace_string); Chris@16: } Chris@16: else { Chris@16: boost::algorithm::erase_all(format, Chris@16: fractional_seconds_or_none_format); Chris@16: } Chris@16: } Chris@16: Chris@16: return this->do_put_tm(next_arg, ios_arg, fill_arg, Chris@16: to_tm(time_dur_arg), format); Chris@16: } Chris@16: Chris@16: OutItrT put(OutItrT next, std::ios_base& ios_arg, Chris@16: char_type fill, const period_type& p) const Chris@16: { Chris@16: return this->m_period_formatter.put_period(next, ios_arg, fill,p,*this); Chris@16: } Chris@16: Chris@16: Chris@16: protected: Chris@16: Chris@16: static Chris@16: string_type Chris@16: fractional_seconds_as_string(const time_duration_type& time_arg, Chris@16: bool null_when_zero) Chris@16: { Chris@16: typename time_duration_type::fractional_seconds_type frac_sec = Chris@16: time_arg.fractional_seconds(); Chris@16: Chris@16: if (null_when_zero && (frac_sec == 0)) { Chris@16: return string_type(); Chris@16: } Chris@16: Chris@16: //make sure there is no sign Chris@16: return integral_as_string( Chris@16: date_time::absolute_value(frac_sec), Chris@16: time_duration_type::num_fractional_digits()); Chris@16: } Chris@16: Chris@16: static Chris@16: string_type Chris@16: hours_as_string(const time_duration_type& time_arg, int width = 2) Chris@16: { Chris@16: return integral_as_string(date_time::absolute_value(time_arg.hours()), width); Chris@16: } Chris@16: Chris@16: template< typename IntT > Chris@16: static Chris@16: string_type Chris@16: integral_as_string(IntT val, int width = 2) Chris@16: { Chris@16: std::basic_ostringstream ss; Chris@16: ss.imbue(std::locale::classic()); // don't want any formatting Chris@16: ss << std::setw(width) Chris@16: << std::setfill(static_cast('0')); Chris@16: #if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) Chris@16: // JDG [7/6/02 VC++ compatibility] Chris@16: char_type buff[34]; Chris@16: ss << _i64toa(static_cast(val), buff, 10); Chris@16: #else Chris@16: ss << val; Chris@16: #endif Chris@16: return ss.str(); Chris@16: } Chris@16: Chris@16: private: Chris@16: string_type m_time_duration_format; Chris@16: Chris@16: }; Chris@16: Chris@16: template Chris@16: std::locale::id time_facet::id; Chris@16: Chris@16: template Chris@16: const typename time_facet::char_type* Chris@16: time_facet::fractional_seconds_format = time_formats::fractional_seconds_format; Chris@16: Chris@16: template Chris@16: const typename time_facet::char_type* Chris@16: time_facet::fractional_seconds_or_none_format = time_formats::fractional_seconds_or_none_format; Chris@16: Chris@16: template Chris@16: const typename time_facet::char_type* Chris@16: time_facet::seconds_with_fractional_seconds_format = Chris@16: time_formats::seconds_with_fractional_seconds_format; Chris@16: Chris@16: Chris@16: template Chris@16: const typename time_facet::char_type* Chris@16: time_facet::zone_name_format = time_formats::zone_name_format; Chris@16: Chris@16: template Chris@16: const typename time_facet::char_type* Chris@16: time_facet::zone_abbrev_format = time_formats::zone_abbrev_format; Chris@16: Chris@16: template Chris@16: const typename time_facet::char_type* Chris@16: time_facet::zone_iso_extended_format =time_formats::zone_iso_extended_format; Chris@16: Chris@16: template Chris@16: const typename time_facet::char_type* Chris@16: time_facet::posix_zone_string_format =time_formats::posix_zone_string_format; Chris@16: Chris@16: template Chris@16: const typename time_facet::char_type* Chris@16: time_facet::zone_iso_format = time_formats::zone_iso_format; Chris@16: Chris@16: template Chris@16: const typename time_facet::char_type* Chris@16: time_facet::seconds_format = time_formats::seconds_format; Chris@16: Chris@16: template Chris@16: const typename time_facet::char_type* Chris@16: time_facet::hours_format = time_formats::hours_format; Chris@16: Chris@16: template Chris@16: const typename time_facet::char_type* Chris@16: time_facet::unrestricted_hours_format = time_formats::unrestricted_hours_format; Chris@16: Chris@16: template Chris@16: const typename time_facet::char_type* Chris@16: time_facet::standard_format = time_formats::standard_format; Chris@16: Chris@16: template Chris@16: const typename time_facet::char_type* Chris@16: time_facet::duration_seperator = time_formats::duration_seperator; Chris@16: Chris@16: template Chris@16: const typename time_facet::char_type* Chris@16: time_facet::negative_sign = time_formats::negative_sign; Chris@16: Chris@16: template Chris@16: const typename time_facet::char_type* Chris@16: time_facet::positive_sign = time_formats::positive_sign; Chris@16: Chris@16: template Chris@16: const typename time_facet::char_type* Chris@16: time_facet::duration_sign_negative_only = time_formats::duration_sign_negative_only; Chris@16: Chris@16: template Chris@16: const typename time_facet::char_type* Chris@16: time_facet::duration_sign_always = time_formats::duration_sign_always; Chris@16: Chris@16: template Chris@16: const typename time_facet::char_type* Chris@16: time_facet::iso_time_format_specifier = time_formats::iso_time_format_specifier; Chris@16: Chris@16: template Chris@16: const typename time_facet::char_type* Chris@16: time_facet::iso_time_format_extended_specifier = time_formats::iso_time_format_extended_specifier; Chris@16: Chris@16: template Chris@16: const typename time_facet::char_type* Chris@16: time_facet::default_time_format = Chris@16: time_formats::default_time_format; Chris@16: Chris@16: template Chris@16: const typename time_facet::char_type* Chris@16: time_facet::default_time_duration_format = Chris@16: time_formats::default_time_duration_format; Chris@16: Chris@16: Chris@16: //! Facet for format-based input. Chris@16: /*! Chris@16: */ Chris@16: template > > Chris@16: class time_input_facet : Chris@16: public boost::date_time::date_input_facet { Chris@16: public: Chris@16: typedef typename time_type::date_type date_type; Chris@16: typedef typename time_type::time_duration_type time_duration_type; Chris@16: typedef typename time_duration_type::fractional_seconds_type fracional_seconds_type; Chris@16: typedef boost::date_time::period period_type; Chris@16: typedef boost::date_time::date_input_facet base_type; Chris@16: typedef typename base_type::duration_type date_duration_type; Chris@16: typedef typename base_type::year_type year_type; Chris@16: typedef typename base_type::month_type month_type; Chris@16: typedef typename base_type::day_type day_type; Chris@16: typedef typename base_type::string_type string_type; Chris@16: typedef typename string_type::const_iterator const_itr; Chris@16: typedef typename base_type::char_type char_type; Chris@16: typedef typename base_type::format_date_parser_type format_date_parser_type; Chris@16: typedef typename base_type::period_parser_type period_parser_type; Chris@16: typedef typename base_type::special_values_parser_type special_values_parser_type; Chris@16: typedef typename base_type::date_gen_parser_type date_gen_parser_type; Chris@16: typedef typename base_type::special_values_parser_type::match_results match_results; Chris@16: Chris@16: static const char_type* fractional_seconds_format; // f Chris@16: static const char_type* fractional_seconds_or_none_format; // F Chris@16: static const char_type* seconds_with_fractional_seconds_format; // s Chris@16: static const char_type* seconds_format; // S Chris@16: static const char_type* standard_format; // x X Chris@16: static const char_type* zone_abbrev_format; // z Chris@16: static const char_type* zone_name_format; // Z Chris@16: static const char_type* zone_iso_format; // q Chris@16: static const char_type* zone_iso_extended_format; // Q Chris@16: static const char_type* duration_seperator; Chris@16: static const char_type* iso_time_format_specifier; Chris@16: static const char_type* iso_time_format_extended_specifier; Chris@16: static const char_type* default_time_input_format; Chris@16: static const char_type* default_time_duration_format; Chris@16: static std::locale::id id; Chris@16: Chris@16: //! Constructor that takes a format string for a ptime Chris@16: explicit time_input_facet(const string_type& format, ::size_t ref_arg = 0) Chris@16: : base_type(format, ref_arg), Chris@16: m_time_duration_format(default_time_duration_format) Chris@16: { } Chris@16: Chris@16: explicit time_input_facet(const string_type& format, Chris@16: const format_date_parser_type& date_parser, Chris@16: const special_values_parser_type& sv_parser, Chris@16: const period_parser_type& per_parser, Chris@16: const date_gen_parser_type& date_gen_parser, Chris@16: ::size_t ref_arg = 0) Chris@16: : base_type(format, Chris@16: date_parser, Chris@16: sv_parser, Chris@16: per_parser, Chris@16: date_gen_parser, Chris@16: ref_arg), Chris@16: m_time_duration_format(default_time_duration_format) Chris@16: {} Chris@16: Chris@16: //! sets default formats for ptime, local_date_time, and time_duration Chris@16: explicit time_input_facet(::size_t ref_arg = 0) Chris@16: : base_type(default_time_input_format, ref_arg), Chris@16: m_time_duration_format(default_time_duration_format) Chris@16: { } Chris@16: Chris@16: //! Set the format for time_duration Chris@16: void time_duration_format(const char_type* const format) { Chris@16: m_time_duration_format = format; Chris@16: } Chris@16: virtual void set_iso_format() Chris@16: { Chris@16: this->m_format = iso_time_format_specifier; Chris@16: } Chris@16: virtual void set_iso_extended_format() Chris@16: { Chris@16: this->m_format = iso_time_format_extended_specifier; Chris@16: } Chris@16: Chris@16: InItrT get(InItrT& sitr, Chris@16: InItrT& stream_end, Chris@16: std::ios_base& ios_arg, Chris@16: period_type& p) const Chris@16: { Chris@16: p = this->m_period_parser.get_period(sitr, Chris@16: stream_end, Chris@16: ios_arg, Chris@16: p, Chris@16: time_duration_type::unit(), Chris@16: *this); Chris@16: return sitr; Chris@16: } Chris@16: Chris@16: //default ptime format is YYYY-Mon-DD HH:MM:SS[.fff...][ zzz] Chris@16: //default time_duration format is %H:%M:%S%F HH:MM:SS[.fff...] Chris@16: Chris@16: InItrT get(InItrT& sitr, Chris@16: InItrT& stream_end, Chris@16: std::ios_base& ios_arg, Chris@16: time_duration_type& td) const Chris@16: { Chris@16: // skip leading whitespace Chris@16: while((sitr != stream_end) && std::isspace(*sitr)) { ++sitr; } Chris@16: Chris@16: bool use_current_char = false; Chris@16: Chris@16: // num_get will consume the +/-, we may need a copy if special_value Chris@16: char_type c = '\0'; Chris@16: if((sitr != stream_end) && (*sitr == '-' || *sitr == '+')) { Chris@16: c = *sitr; Chris@16: } Chris@16: Chris@16: typedef typename time_duration_type::hour_type hour_type; Chris@16: typedef typename time_duration_type::min_type min_type; Chris@16: typedef typename time_duration_type::sec_type sec_type; Chris@16: Chris@16: hour_type hour = 0; Chris@16: min_type min = 0; Chris@16: sec_type sec = 0; Chris@16: typename time_duration_type::fractional_seconds_type frac(0); Chris@16: Chris@16: typedef std::num_get num_get; Chris@16: if(!std::has_facet(ios_arg.getloc())) { Chris@16: num_get* ng = new num_get(); Chris@16: std::locale loc = std::locale(ios_arg.getloc(), ng); Chris@16: ios_arg.imbue(loc); Chris@16: } Chris@16: Chris@16: const_itr itr(m_time_duration_format.begin()); Chris@16: while (itr != m_time_duration_format.end() && (sitr != stream_end)) { Chris@16: if (*itr == '%') { Chris@16: if (++itr == m_time_duration_format.end()) break; Chris@16: if (*itr != '%') { Chris@16: switch(*itr) { Chris@16: case 'O': Chris@16: { Chris@16: // A period may span more than 24 hours. In that case the format Chris@16: // string should be composed with the unrestricted hours specifier. Chris@16: hour = var_string_to_int(sitr, stream_end, Chris@16: std::numeric_limits::digits10 + 1); Chris@16: if(hour == -1){ Chris@16: return check_special_value(sitr, stream_end, td, c); Chris@16: } Chris@16: break; Chris@16: } Chris@16: case 'H': Chris@16: { Chris@16: match_results mr; Chris@16: hour = fixed_string_to_int(sitr, stream_end, mr, 2); Chris@16: if(hour == -1){ Chris@16: return check_special_value(sitr, stream_end, td, c); Chris@16: } Chris@16: break; Chris@16: } Chris@16: case 'M': Chris@16: { Chris@16: match_results mr; Chris@16: min = fixed_string_to_int(sitr, stream_end, mr, 2); Chris@16: if(min == -1){ Chris@16: return check_special_value(sitr, stream_end, td, c); Chris@16: } Chris@16: break; Chris@16: } Chris@16: case 's': Chris@16: case 'S': Chris@16: { Chris@16: match_results mr; Chris@16: sec = fixed_string_to_int(sitr, stream_end, mr, 2); Chris@16: if(sec == -1){ Chris@16: return check_special_value(sitr, stream_end, td, c); Chris@16: } Chris@16: if (*itr == 'S') Chris@16: break; Chris@16: // %s is the same as %S%f so we drop through into %f Chris@16: } Chris@16: case 'f': Chris@16: { Chris@16: // check for decimal, check special_values if missing Chris@16: if(*sitr == '.') { Chris@16: ++sitr; Chris@16: parse_frac_type(sitr, stream_end, frac); Chris@16: // sitr will point to next expected char after this parsing Chris@16: // is complete so no need to advance it Chris@16: use_current_char = true; Chris@16: } Chris@16: else { Chris@16: return check_special_value(sitr, stream_end, td, c); Chris@16: } Chris@16: break; Chris@16: } Chris@16: case 'F': Chris@16: { Chris@16: // check for decimal, skip if missing Chris@16: if(*sitr == '.') { Chris@16: ++sitr; Chris@16: parse_frac_type(sitr, stream_end, frac); Chris@16: // sitr will point to next expected char after this parsing Chris@16: // is complete so no need to advance it Chris@16: use_current_char = true; Chris@16: } Chris@16: else { Chris@16: // nothing was parsed so we don't want to advance sitr Chris@16: use_current_char = true; Chris@16: } Chris@16: break; Chris@16: } Chris@16: default: Chris@16: {} // ignore what we don't understand? Chris@16: }// switch Chris@16: } Chris@16: else { // itr == '%', second consecutive Chris@16: ++sitr; Chris@16: } Chris@16: Chris@16: ++itr; //advance past format specifier Chris@16: } Chris@16: else { //skip past chars in format and in buffer Chris@16: ++itr; Chris@16: // set use_current_char when sitr is already Chris@16: // pointing at the next character to process Chris@16: if (use_current_char) { Chris@16: use_current_char = false; Chris@16: } Chris@16: else { Chris@16: ++sitr; Chris@16: } Chris@16: } Chris@16: } Chris@16: Chris@16: td = time_duration_type(hour, min, sec, frac); Chris@16: return sitr; Chris@16: } Chris@16: Chris@16: Chris@16: //! Parses a time object from the input stream Chris@16: InItrT get(InItrT& sitr, Chris@16: InItrT& stream_end, Chris@16: std::ios_base& ios_arg, Chris@16: time_type& t) const Chris@16: { Chris@16: string_type tz_str; Chris@16: return get(sitr, stream_end, ios_arg, t, tz_str, false); Chris@16: } Chris@16: //! Expects a time_zone in the input stream Chris@16: InItrT get_local_time(InItrT& sitr, Chris@16: InItrT& stream_end, Chris@16: std::ios_base& ios_arg, Chris@16: time_type& t, Chris@16: string_type& tz_str) const Chris@16: { Chris@16: return get(sitr, stream_end, ios_arg, t, tz_str, true); Chris@16: } Chris@16: Chris@16: protected: Chris@16: Chris@16: InItrT get(InItrT& sitr, Chris@16: InItrT& stream_end, Chris@16: std::ios_base& ios_arg, Chris@16: time_type& t, Chris@16: string_type& tz_str, Chris@16: bool time_is_local) const Chris@16: { Chris@16: // skip leading whitespace Chris@16: while((sitr != stream_end) && std::isspace(*sitr)) { ++sitr; } Chris@16: Chris@16: bool use_current_char = false; Chris@16: bool use_current_format_char = false; // used whith two character flags Chris@16: Chris@16: // num_get will consume the +/-, we may need a copy if special_value Chris@16: char_type c = '\0'; Chris@16: if((sitr != stream_end) && (*sitr == '-' || *sitr == '+')) { Chris@16: c = *sitr; Chris@16: } Chris@16: Chris@16: typedef typename time_duration_type::hour_type hour_type; Chris@16: typedef typename time_duration_type::min_type min_type; Chris@16: typedef typename time_duration_type::sec_type sec_type; Chris@16: Chris@16: // time elements Chris@16: hour_type hour = 0; Chris@16: min_type min = 0; Chris@16: sec_type sec = 0; Chris@16: typename time_duration_type::fractional_seconds_type frac(0); Chris@16: // date elements Chris@16: short day_of_year(0); Chris@16: /* Initialized the following to their minimum values. These intermediate Chris@16: * objects are used so we get specific exceptions when part of the input Chris@16: * is unparsable. Chris@16: * Ex: "205-Jan-15" will throw a bad_year, "2005-Jsn-15"- bad_month, etc.*/ Chris@16: year_type t_year(1400); Chris@16: month_type t_month(1); Chris@16: day_type t_day(1); Chris@16: Chris@16: typedef std::num_get num_get; Chris@16: if(!std::has_facet(ios_arg.getloc())) { Chris@16: num_get* ng = new num_get(); Chris@16: std::locale loc = std::locale(ios_arg.getloc(), ng); Chris@16: ios_arg.imbue(loc); Chris@16: } Chris@16: Chris@16: const_itr itr(this->m_format.begin()); Chris@16: while (itr != this->m_format.end() && (sitr != stream_end)) { Chris@16: if (*itr == '%') { Chris@16: if (++itr == this->m_format.end()) break; Chris@16: if (*itr != '%') { Chris@16: // the cases are grouped by date & time flags - not alphabetical order Chris@16: switch(*itr) { Chris@16: // date flags Chris@16: case 'Y': Chris@16: case 'y': Chris@16: { Chris@16: char_type cs[3] = { '%', *itr }; Chris@16: string_type s(cs); Chris@16: match_results mr; Chris@16: try { Chris@16: t_year = this->m_parser.parse_year(sitr, stream_end, s, mr); Chris@16: } Chris@16: catch(std::out_of_range&) { // base class for bad_year exception Chris@16: if(this->m_sv_parser.match(sitr, stream_end, mr)) { Chris@16: t = time_type(static_cast(mr.current_match)); Chris@16: return sitr; Chris@16: } Chris@16: else { Chris@16: throw; // rethrow bad_year Chris@16: } Chris@16: } Chris@16: break; Chris@16: } Chris@16: case 'B': Chris@16: case 'b': Chris@16: case 'm': Chris@16: { Chris@16: char_type cs[3] = { '%', *itr }; Chris@16: string_type s(cs); Chris@16: match_results mr; Chris@16: try { Chris@16: t_month = this->m_parser.parse_month(sitr, stream_end, s, mr); Chris@16: } Chris@16: catch(std::out_of_range&) { // base class for bad_month exception Chris@16: if(this->m_sv_parser.match(sitr, stream_end, mr)) { Chris@16: t = time_type(static_cast(mr.current_match)); Chris@16: return sitr; Chris@16: } Chris@16: else { Chris@16: throw; // rethrow bad_month Chris@16: } Chris@16: } Chris@16: // did m_parser already advance sitr to next char? Chris@16: if(mr.has_remaining()) { Chris@16: use_current_char = true; Chris@16: } Chris@16: break; Chris@16: } Chris@16: case 'a': Chris@16: case 'A': Chris@16: case 'w': Chris@16: { Chris@16: // weekday is not used in construction but we need to get it out of the stream Chris@16: char_type cs[3] = { '%', *itr }; Chris@16: string_type s(cs); Chris@16: match_results mr; Chris@16: typename date_type::day_of_week_type wd(0); Chris@16: try { Chris@16: wd = this->m_parser.parse_weekday(sitr, stream_end, s, mr); Chris@16: } Chris@16: catch(std::out_of_range&) { // base class for bad_weekday exception Chris@16: if(this->m_sv_parser.match(sitr, stream_end, mr)) { Chris@16: t = time_type(static_cast(mr.current_match)); Chris@16: return sitr; Chris@16: } Chris@16: else { Chris@16: throw; // rethrow bad_weekday Chris@16: } Chris@16: } Chris@16: // did m_parser already advance sitr to next char? Chris@16: if(mr.has_remaining()) { Chris@16: use_current_char = true; Chris@16: } Chris@16: break; Chris@16: } Chris@16: case 'j': Chris@16: { Chris@16: // code that gets julian day (from format_date_parser) Chris@16: match_results mr; Chris@16: day_of_year = fixed_string_to_int(sitr, stream_end, mr, 3); Chris@16: if(day_of_year == -1) { Chris@16: if(this->m_sv_parser.match(sitr, stream_end, mr)) { Chris@16: t = time_type(static_cast(mr.current_match)); Chris@16: return sitr; Chris@16: } Chris@16: } Chris@16: // these next two lines are so we get an exception with bad input Chris@16: typedef typename time_type::date_type::day_of_year_type day_of_year_type; Chris@16: day_of_year_type t_day_of_year(day_of_year); Chris@16: break; Chris@16: } Chris@16: case 'd': Chris@16: { Chris@16: try { Chris@16: t_day = this->m_parser.parse_day_of_month(sitr, stream_end); Chris@16: } Chris@16: catch(std::out_of_range&) { // base class for exception bad_day_of_month Chris@16: match_results mr; Chris@16: if(this->m_sv_parser.match(sitr, stream_end, mr)) { Chris@16: t = time_type(static_cast(mr.current_match)); Chris@16: return sitr; Chris@16: } Chris@16: else { Chris@16: throw; // rethrow bad_day_of_month Chris@16: } Chris@16: } Chris@16: break; Chris@16: } Chris@16: // time flags Chris@16: case 'H': Chris@16: { Chris@16: match_results mr; Chris@16: hour = fixed_string_to_int(sitr, stream_end, mr, 2); Chris@16: if(hour == -1){ Chris@16: return check_special_value(sitr, stream_end, t, c); Chris@16: } Chris@16: break; Chris@16: } Chris@16: case 'M': Chris@16: { Chris@16: match_results mr; Chris@16: min = fixed_string_to_int(sitr, stream_end, mr, 2); Chris@16: if(min == -1){ Chris@16: return check_special_value(sitr, stream_end, t, c); Chris@16: } Chris@16: break; Chris@16: } Chris@16: case 's': Chris@16: case 'S': Chris@16: { Chris@16: match_results mr; Chris@16: sec = fixed_string_to_int(sitr, stream_end, mr, 2); Chris@16: if(sec == -1){ Chris@16: return check_special_value(sitr, stream_end, t, c); Chris@16: } Chris@16: if (*itr == 'S') Chris@16: break; Chris@16: // %s is the same as %S%f so we drop through into %f Chris@16: } Chris@16: case 'f': Chris@16: { Chris@16: // check for decimal, check SV if missing Chris@16: if(*sitr == '.') { Chris@16: ++sitr; Chris@16: parse_frac_type(sitr, stream_end, frac); Chris@16: // sitr will point to next expected char after this parsing Chris@16: // is complete so no need to advance it Chris@16: use_current_char = true; Chris@16: } Chris@16: else { Chris@16: return check_special_value(sitr, stream_end, t, c); Chris@16: } Chris@16: break; Chris@16: } Chris@16: case 'F': Chris@16: { Chris@16: // check for decimal, skip if missing Chris@16: if(*sitr == '.') { Chris@16: ++sitr; Chris@16: parse_frac_type(sitr, stream_end, frac); Chris@16: // sitr will point to next expected char after this parsing Chris@16: // is complete so no need to advance it Chris@16: use_current_char = true; Chris@16: } Chris@16: else { Chris@16: // nothing was parsed so we don't want to advance sitr Chris@16: use_current_char = true; Chris@16: } Chris@16: break; Chris@16: } Chris@16: // time_zone flags Chris@16: //case 'q': Chris@16: //case 'Q': Chris@16: //case 'z': Chris@16: case 'Z': Chris@16: { Chris@16: if(time_is_local) { // skip if 't' is a ptime Chris@16: ++itr; Chris@16: if(*itr == 'P') { Chris@16: // skip leading whitespace Chris@16: while((sitr != stream_end) && std::isspace(*sitr)) { ++sitr; } Chris@16: // parse zone Chris@16: while((sitr != stream_end) && (!std::isspace(*sitr))) { Chris@16: tz_str += *sitr; Chris@16: ++sitr; Chris@16: } Chris@16: } Chris@16: else { Chris@16: use_current_format_char = true; Chris@16: } Chris@16: Chris@16: } Chris@16: else { Chris@16: // nothing was parsed so we don't want to advance sitr Chris@16: use_current_char = true; Chris@16: } Chris@16: Chris@16: break; Chris@16: } Chris@16: default: Chris@16: {} // ignore what we don't understand? Chris@16: }// switch Chris@16: } Chris@16: else { // itr == '%', second consecutive Chris@16: ++sitr; Chris@16: } Chris@16: Chris@16: if(use_current_format_char) { Chris@16: use_current_format_char = false; Chris@16: } Chris@16: else { Chris@16: ++itr; //advance past format specifier Chris@16: } Chris@16: Chris@16: } Chris@16: else { //skip past chars in format and in buffer Chris@16: ++itr; Chris@16: // set use_current_char when sitr is already Chris@16: // pointing at the next character to process Chris@16: if (use_current_char) { Chris@16: use_current_char = false; Chris@16: } Chris@16: else { Chris@16: ++sitr; Chris@16: } Chris@16: } Chris@16: } Chris@16: Chris@16: date_type d(not_a_date_time); Chris@16: if (day_of_year > 0) { Chris@16: d = date_type(static_cast(t_year-1),12,31) + date_duration_type(day_of_year); Chris@16: } Chris@16: else { Chris@16: d = date_type(t_year, t_month, t_day); Chris@16: } Chris@16: Chris@16: time_duration_type td(hour, min, sec, frac); Chris@16: t = time_type(d, td); Chris@16: return sitr; Chris@16: } Chris@16: Chris@16: //! Helper function to check for special_value Chris@16: /*! First character may have been consumed during original parse Chris@16: * attempt. Parameter 'c' should be a copy of that character. Chris@16: * Throws ios_base::failure if parse fails. */ Chris@16: template Chris@16: inline Chris@16: InItrT check_special_value(InItrT& sitr,InItrT& stream_end, temporal_type& tt, char_type c='\0') const Chris@16: { Chris@16: match_results mr; Chris@16: if((c == '-' || c == '+') && (*sitr != c)) { // was the first character consumed? Chris@16: mr.cache += c; Chris@16: } Chris@16: this->m_sv_parser.match(sitr, stream_end, mr); Chris@16: if(mr.current_match == match_results::PARSE_ERROR) { Chris@16: std::string tmp = convert_string_type(mr.cache); Chris@16: boost::throw_exception(std::ios_base::failure("Parse failed. No match found for '" + tmp + "'")); Chris@16: BOOST_DATE_TIME_UNREACHABLE_EXPRESSION(return sitr); // should never reach Chris@16: } Chris@16: tt = temporal_type(static_cast(mr.current_match)); Chris@16: return sitr; Chris@16: } Chris@16: Chris@16: //! Helper function for parsing a fractional second type from the stream Chris@16: void parse_frac_type(InItrT& sitr, Chris@16: InItrT& stream_end, Chris@16: fracional_seconds_type& frac) const Chris@16: { Chris@16: string_type cache; Chris@16: while((sitr != stream_end) && std::isdigit(*sitr)) { Chris@16: cache += *sitr; Chris@16: ++sitr; Chris@16: } Chris@16: if(cache.size() > 0) { Chris@16: unsigned short precision = time_duration_type::num_fractional_digits(); Chris@16: // input may be only the first few decimal places Chris@16: if(cache.size() < precision) { Chris@16: frac = lexical_cast(cache); Chris@16: frac = decimal_adjust(frac, static_cast(precision - cache.size())); Chris@16: } Chris@16: else { Chris@16: // if input has too many decimal places, drop excess digits Chris@16: frac = lexical_cast(cache.substr(0, precision)); Chris@16: } Chris@16: } Chris@16: } Chris@16: Chris@16: private: Chris@16: string_type m_time_duration_format; Chris@16: Chris@16: //! Helper function to adjust trailing zeros when parsing fractional digits Chris@16: template Chris@16: inline Chris@16: int_type decimal_adjust(int_type val, const unsigned short places) const Chris@16: { Chris@16: unsigned long factor = 1; Chris@16: for(int i = 0; i < places; ++i){ Chris@16: factor *= 10; // shift decimal to the right Chris@16: } Chris@16: return val * factor; Chris@16: } Chris@16: Chris@16: }; Chris@16: Chris@16: template Chris@16: std::locale::id time_input_facet::id; Chris@16: Chris@16: template Chris@16: const typename time_input_facet::char_type* Chris@16: time_input_facet::fractional_seconds_format = time_formats::fractional_seconds_format; Chris@16: Chris@16: template Chris@16: const typename time_input_facet::char_type* Chris@16: time_input_facet::fractional_seconds_or_none_format = time_formats::fractional_seconds_or_none_format; Chris@16: Chris@16: template Chris@16: const typename time_input_facet::char_type* Chris@16: time_input_facet::seconds_with_fractional_seconds_format = time_formats::seconds_with_fractional_seconds_format; Chris@16: Chris@16: template Chris@16: const typename time_input_facet::char_type* Chris@16: time_input_facet::seconds_format = time_formats::seconds_format; Chris@16: Chris@16: template Chris@16: const typename time_input_facet::char_type* Chris@16: time_input_facet::standard_format = time_formats::standard_format; Chris@16: Chris@16: template Chris@16: const typename time_input_facet::char_type* Chris@16: time_input_facet::zone_abbrev_format = time_formats::zone_abbrev_format; Chris@16: Chris@16: template Chris@16: const typename time_input_facet::char_type* Chris@16: time_input_facet::zone_name_format = time_formats::zone_name_format; Chris@16: Chris@16: template Chris@16: const typename time_input_facet::char_type* Chris@16: time_input_facet::zone_iso_format = time_formats::zone_iso_format; Chris@16: Chris@16: template Chris@16: const typename time_input_facet::char_type* Chris@16: time_input_facet::zone_iso_extended_format = time_formats::zone_iso_extended_format; Chris@16: Chris@16: template Chris@16: const typename time_input_facet::char_type* Chris@16: time_input_facet::duration_seperator = time_formats::duration_seperator; Chris@16: Chris@16: template Chris@16: const typename time_input_facet::char_type* Chris@16: time_input_facet::iso_time_format_specifier = time_formats::iso_time_format_specifier; Chris@16: Chris@16: template Chris@16: const typename time_input_facet::char_type* Chris@16: time_input_facet::iso_time_format_extended_specifier = time_formats::iso_time_format_extended_specifier; Chris@16: Chris@16: template Chris@16: const typename time_input_facet::char_type* Chris@16: time_input_facet::default_time_input_format = time_formats::default_time_input_format; Chris@16: Chris@16: template Chris@16: const typename time_input_facet::char_type* Chris@16: time_input_facet::default_time_duration_format = time_formats::default_time_duration_format; Chris@16: Chris@16: Chris@16: } } // namespaces Chris@16: Chris@16: Chris@16: #endif Chris@16: