From 94de7178572428dc8842f13e30865a65aa57948b Mon Sep 17 00:00:00 2001 From: Jeff Garland Date: Sun, 30 Jan 2005 20:58:52 +0000 Subject: [PATCH] large series of changes associated with revamped facet code [SVN r26940] --- include/boost/date_time/date_facet.hpp | 149 ++++++++++- .../date_time/date_generator_formatter.hpp | 205 ++++++++++++++ .../boost/date_time/gregorian/conversion.hpp | 21 +- .../boost/date_time/gregorian/formatters.hpp | 1 - .../gregorian/formatters_limited.hpp | 1 - .../boost/date_time/gregorian/greg_facet.hpp | 3 +- .../boost/date_time/gregorian/gregorian.hpp | 6 + .../date_time/gregorian/gregorian_io.hpp | 249 ++++++++++++++++++ .../date_time/local_time/local_date_time.hpp | 136 ++++++++-- .../date_time/local_time/posix_time_zone.hpp | 51 ++-- .../boost/date_time/posix_time/conversion.hpp | 20 +- .../boost/date_time/posix_time/posix_time.hpp | 14 +- .../date_time/posix_time/posix_time_io.hpp | 117 ++++++++ .../date_time/posix_time/time_formatters.hpp | 124 --------- .../posix_time/time_formatters_limited.hpp | 45 ---- .../boost/date_time/strings_from_facet.hpp | 5 + include/boost/date_time/time.hpp | 12 +- include/boost/date_time/time_facet.hpp | 211 +++++++++++++-- 18 files changed, 1118 insertions(+), 252 deletions(-) create mode 100644 include/boost/date_time/date_generator_formatter.hpp create mode 100644 include/boost/date_time/gregorian/gregorian_io.hpp create mode 100644 include/boost/date_time/posix_time/posix_time_io.hpp diff --git a/include/boost/date_time/date_facet.hpp b/include/boost/date_time/date_facet.hpp index b28adca..6be6264 100644 --- a/include/boost/date_time/date_facet.hpp +++ b/include/boost/date_time/date_facet.hpp @@ -5,7 +5,7 @@ * Use, modification and distribution is subject to the * Boost Software License, Version 1.0. (See accompanying * file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) - * Author: Martin Andrian, Jeff Garland + * Author: Martin Andrian, Jeff Garland, Bart Garst * $Date$ */ @@ -14,24 +14,50 @@ #include "boost/date_time/period.hpp" #include "boost/date_time/special_values_formatter.hpp" #include "boost/date_time/period_formatter.hpp" +#include "boost/date_time/date_generator_formatter.hpp" #include #include namespace boost { namespace date_time { + /*! TODO: ... + * Format flags are: + * + * %A => long_weekday_format - Full name Ex: Tuesday + * %a => short_weekday_format - Three letter abbreviation Ex: Tue + * %B => long_month_format - Full name Ex: October + * %b => short_month_format - Three letter abbreviation Ex: Oct + * %x => standard_format_specifier - defined by the locale + * %Y-%b-%d => default_date_format - YYYY-Mon-dd + * + * Default month format == %b + * Default weekday format == %a + */ template > > class date_facet : public std::locale::facet { public: typedef typename date_type::duration_type duration_type; + // greg_weekday is gregorian_calendar::day_of_week_type + typedef typename date_type::day_of_week_type day_of_week_type; + typedef typename date_type::day_type day_type; + typedef typename date_type::month_type month_type; typedef boost::date_time::period period_type; typedef std::basic_string string_type; typedef CharT char_type; typedef boost::date_time::period_formatter period_formatter_type; typedef boost::date_time::special_values_formatter special_values_formatter_type; typedef std::vector > input_collection_type; + // used for the output of the date_generators + typedef date_generator_formatter date_gen_formatter_type; + typedef partial_date partial_date_type; + typedef nth_kday_of_month nth_kday_type; + typedef first_kday_of_month first_kday_type; + typedef last_kday_of_month last_kday_type; + typedef first_kday_after kday_after_type; + typedef first_kday_before kday_before_type; static const char_type long_weekday_format[3]; static const char_type short_weekday_format[3]; static const char_type long_month_format[3]; @@ -40,11 +66,15 @@ namespace boost { namespace date_time { static const char_type standard_format_specifier[3]; static const char_type iso_format_specifier[7]; static const char_type iso_format_extended_specifier[9]; + static const char_type default_date_format[9]; // YYYY-Mon-DD static std::locale::id id; explicit date_facet(::size_t a_ref = 0) : std::locale::facet(a_ref), - m_format(standard_format_specifier) + //m_format(standard_format_specifier) + m_format(default_date_format), + m_month_format(short_month_format), + m_weekday_format(short_weekday_format) {} explicit date_facet(const char_type* format, @@ -52,6 +82,8 @@ namespace boost { namespace date_time { ::size_t ref_count = 0) : std::locale::facet(ref_count), m_format(format), + m_month_format(short_month_format), + m_weekday_format(short_weekday_format), m_month_short_names(short_month_names) {} @@ -59,10 +91,14 @@ namespace boost { namespace date_time { explicit date_facet(const char_type* format, period_formatter_type period_formatter = period_formatter_type(), special_values_formatter_type special_values_formatter = special_values_formatter_type(), + date_gen_formatter_type dg_formatter = date_gen_formatter_type(), ::size_t ref_count = 0) : std::locale::facet(ref_count), m_format(format), + m_month_format(short_month_format), + m_weekday_format(short_weekday_format), m_period_formatter(period_formatter), + m_date_gen_formatter(dg_formatter), m_special_values_formatter(special_values_formatter) {} void format(const char_type* const format) { @@ -76,6 +112,12 @@ namespace boost { namespace date_time { { m_format = iso_format_extended_specifier; } + void month_format(const char_type* const format) { + m_month_format = format; + } + void weekday_format(const char_type* const format) { + m_weekday_format = format; + } void period_formatter(period_formatter_type period_formatter) { m_period_formatter= period_formatter; @@ -103,6 +145,12 @@ namespace boost { namespace date_time { m_month_long_names = long_month_names; } + void date_gen_phrase_strings(const input_collection_type& new_strings, + typename date_gen_formatter_type::phrase_elements beg_pos=date_gen_formatter_type::first) + { + m_date_gen_formatter.elements(new_strings, beg_pos); + } + OutItrT put(OutItrT next, std::ios_base& a_ios, char_type fill_char, @@ -115,6 +163,47 @@ namespace boost { namespace date_time { return do_put_tm(next, a_ios, fill_char, to_tm(d), m_format); } + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const month_type& m) const + { + //if (d.is_special()) { + // return do_put_special(next, a_ios, fill_char, d.as_special()); + //} + //The following line of code required the date to support a to_tm function + tm dtm; + dtm.tm_mon = m -1; + return do_put_tm(next, a_ios, fill_char, dtm, m_month_format); + } + + //! puts the day of month + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const day_type& day) const + { + tm dtm; + dtm.tm_mday = day.as_number(); + char_type tmp[3] = {'%','d'}; + string_type temp_format(tmp); + return do_put_tm(next, a_ios, fill_char, dtm, temp_format); + } + + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const day_of_week_type& dow) const + { + //if (d.is_special()) { + // return do_put_special(next, a_ios, fill_char, d.as_special()); + //} + //The following line of code required the date to support a to_tm function + tm dtm; + dtm.tm_wday = dow; + return do_put_tm(next, a_ios, fill_char, dtm, m_weekday_format); + } + // date durations don't interact with the facet...no put code needed here. // todo is that really true? What about special values? @@ -125,6 +214,55 @@ namespace boost { namespace date_time { { return m_period_formatter.put_period(next, a_ios, fill_char, p, *this); } + + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const partial_date_type& pd) const + { + return m_date_gen_formatter.put_partial_date(next, a_ios, fill_char, pd, *this); + } + + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const nth_kday_type& nkd) const + { + return m_date_gen_formatter.put_nth_kday(next, a_ios, fill_char, nkd, *this); + } + + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const first_kday_type& fkd) const + { + return m_date_gen_formatter.put_first_kday(next, a_ios, fill_char, fkd, *this); + } + + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const last_kday_type& lkd) const + { + return m_date_gen_formatter.put_last_kday(next, a_ios, fill_char, lkd, *this); + } + + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const kday_before_type& fkb) const + { + return m_date_gen_formatter.put_kday_before(next, a_ios, fill_char, fkb, *this); + } + + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const kday_after_type& fka) const + { + return m_date_gen_formatter.put_kday_after(next, a_ios, fill_char, fka, *this); + } + protected: virtual OutItrT do_put_special(OutItrT next, std::ios_base& a_ios, @@ -171,7 +309,10 @@ namespace boost { namespace date_time { } protected: string_type m_format; + string_type m_month_format; + string_type m_weekday_format; period_formatter_type m_period_formatter; + date_gen_formatter_type m_date_gen_formatter; special_values_formatter_type m_special_values_formatter; input_collection_type m_month_short_names; input_collection_type m_month_long_names; @@ -218,6 +359,10 @@ namespace boost { namespace date_time { date_facet::iso_format_extended_specifier[9] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd' }; + template + const typename date_facet::char_type + date_facet::default_date_format[9] = + {'%','Y','-','%','b','-','%','d'}; } } diff --git a/include/boost/date_time/date_generator_formatter.hpp b/include/boost/date_time/date_generator_formatter.hpp new file mode 100644 index 0000000..0b8a646 --- /dev/null +++ b/include/boost/date_time/date_generator_formatter.hpp @@ -0,0 +1,205 @@ +#ifndef _DATE_TIME_DATE_GENERATOR_FORMATTER__HPP___ +#define _DATE_TIME_DATE_GENERATOR_FORMATTER__HPP___ + +/* Copyright (c) 2004 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) + * Author: Jeff Garland, Bart Garst + * $Date$ + */ + +#include +#include +#include +#include +#include "boost/date_time/date_generators.hpp" + +namespace boost { +namespace date_time { + + template > > + class date_generator_formatter { + public: + typedef partial_date partial_date_type; + typedef nth_kday_of_month nth_kday_type; + typedef first_kday_of_month first_kday_type; + typedef last_kday_of_month last_kday_type; + typedef first_kday_after kday_after_type; + typedef first_kday_before kday_before_type; + + typedef CharT char_type; + typedef std::basic_string string_type; + typedef std::vector collection_type; + static const char_type first_string[6]; + static const char_type second_string[7]; + static const char_type third_string[6]; + static const char_type fourth_string[7]; + static const char_type fifth_string[6]; + static const char_type last_string[5]; + static const char_type before_string[8]; + static const char_type after_string[6]; + static const char_type of_string[3]; + + enum phrase_elements {first=0, second, third, fourth, fifth, last, + before, after, of, number_of_phrase_elements}; + + date_generator_formatter() + { + phrase_strings.push_back(string_type(first_string)); + phrase_strings.push_back(string_type(second_string)); + phrase_strings.push_back(string_type(third_string)); + phrase_strings.push_back(string_type(fourth_string)); + phrase_strings.push_back(string_type(fifth_string)); + phrase_strings.push_back(string_type(last_string)); + phrase_strings.push_back(string_type(before_string)); + phrase_strings.push_back(string_type(after_string)); + phrase_strings.push_back(string_type(of_string)); + } + + void elements(const collection_type& new_strings, + phrase_elements beg_pos=first) + { + if(beg_pos < number_of_phrase_elements) { + typename collection_type::iterator itr = phrase_strings.begin(); + itr += beg_pos; + std::copy(new_strings.begin(), new_strings.end(), + itr); + //phrase_strings.begin()); + } + } + + template + OutItrT put_partial_date(OutItrT next, std::ios_base& a_ios, + CharT a_fill, const partial_date_type& pd, + const facet_type& facet) const + { + facet.put(next, a_ios, a_fill, pd.day()); + next = a_fill; //TODO change this ??? + facet.put(next, a_ios, a_fill, pd.month()); + return next; + } + + template + OutItrT put_nth_kday(OutItrT next, std::ios_base& a_ios, + CharT a_fill, const nth_kday_type& nkd, + const facet_type& facet) const + { + put_string(next, phrase_strings[nkd.nth_week() -1]); + next = a_fill; //TODO change this ??? + facet.put(next, a_ios, a_fill, nkd.day_of_week()); + next = a_fill; //TODO change this ??? + put_string(next, string_type(of_string)); + next = a_fill; //TODO change this ??? + facet.put(next, a_ios, a_fill, nkd.month()); + return next; + } + + template + OutItrT put_first_kday(OutItrT next, std::ios_base& a_ios, + CharT a_fill, const first_kday_type& fkd, + const facet_type& facet) const + { + put_string(next, phrase_strings[first]); + next = a_fill; //TODO change this ??? + facet.put(next, a_ios, a_fill, fkd.day_of_week()); + next = a_fill; //TODO change this ??? + put_string(next, string_type(of_string)); + next = a_fill; //TODO change this ??? + facet.put(next, a_ios, a_fill, fkd.month()); + return next; + } + + template + OutItrT put_last_kday(OutItrT next, std::ios_base& a_ios, + CharT a_fill, const last_kday_type& lkd, + const facet_type& facet) const + { + put_string(next, phrase_strings[last]); + next = a_fill; //TODO change this ??? + facet.put(next, a_ios, a_fill, lkd.day_of_week()); + next = a_fill; //TODO change this ??? + put_string(next, string_type(of_string)); + next = a_fill; //TODO change this ??? + facet.put(next, a_ios, a_fill, lkd.month()); + return next; + } + + template + OutItrT put_kday_before(OutItrT next, std::ios_base& a_ios, + CharT a_fill, const kday_before_type& fkb, + const facet_type& facet) const + { + facet.put(next, a_ios, a_fill, fkb.day_of_week()); + next = a_fill; //TODO change this ??? + put_string(next, phrase_strings[before]); + return next; + } + + template + OutItrT put_kday_after(OutItrT next, std::ios_base& a_ios, + CharT a_fill, const kday_after_type& fka, + const facet_type& facet) const + { + facet.put(next, a_ios, a_fill, fka.day_of_week()); + next = a_fill; //TODO change this ??? + put_string(next, phrase_strings[after]); + return next; + } + + + private: + collection_type phrase_strings; + + //! helper function to put the various member string into stream + OutItrT put_string(OutItrT next, const string_type& str) const + { + typename string_type::const_iterator itr = str.begin(); + while(itr != str.end()) { + *next = *itr; + ++itr; + ++next; + } + return next; + } + }; + + template + const typename date_generator_formatter::char_type + date_generator_formatter::first_string[6] = + {'f','i','r','s','t'}; + template + const typename date_generator_formatter::char_type + date_generator_formatter::second_string[7] = + {'s','e','c','o','n','d'}; + template + const typename date_generator_formatter::char_type + date_generator_formatter::third_string[6] = + {'t','h','i','r','d'}; + template + const typename date_generator_formatter::char_type + date_generator_formatter::fourth_string[7] = + {'f','o','u','r','t','h'}; + template + const typename date_generator_formatter::char_type + date_generator_formatter::fifth_string[6] = + {'f','i','f','t','h'}; + template + const typename date_generator_formatter::char_type + date_generator_formatter::last_string[5] = + {'l','a','s','t'}; + template + const typename date_generator_formatter::char_type + date_generator_formatter::before_string[8] = + {'b','e','f','o','r','e'}; + template + const typename date_generator_formatter::char_type + date_generator_formatter::after_string[6] = + {'a','f','t','e','r'}; + template + const typename date_generator_formatter::char_type + date_generator_formatter::of_string[3] = + {'o','f'}; +} } // namespaces + +#endif // _DATE_TIME_DATE_GENERATOR_FORMATTER__HPP___ diff --git a/include/boost/date_time/gregorian/conversion.hpp b/include/boost/date_time/gregorian/conversion.hpp index 14ce89c..f36df73 100644 --- a/include/boost/date_time/gregorian/conversion.hpp +++ b/include/boost/date_time/gregorian/conversion.hpp @@ -11,12 +11,17 @@ #include #include "boost/date_time/gregorian/gregorian_types.hpp" -#if defined(BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS) -#include "boost/date_time/gregorian/formatters_limited.hpp" -#else -#include "boost/date_time/gregorian/formatters.hpp" -#endif // BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS #include "boost/date_time/c_time.hpp" +#if defined(USE_DATE_TIME_PRE_1_33_FACET_IO) +# if defined(BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS) +# include "boost/date_time/gregorian/formatters_limited.hpp" +# else +# include "boost/date_time/gregorian/formatters.hpp" +# endif // BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS +#else +# include +# include "boost/date_time/gregorian/gregorian_io.hpp" +#endif // USE_DATE_TIME_PRE_1_33_FACET_IO namespace boost { @@ -28,8 +33,14 @@ namespace gregorian { tm to_tm(const date& d) { if(d.is_pos_infinity() || d.is_neg_infinity() || d.is_not_a_date()){ +#if defined(USE_DATE_TIME_PRE_1_33_FACET_IO) std::string s("tm unable to handle date value of " + to_simple_string(d)); throw std::out_of_range(s); +#else + std::stringstream ss; + ss << "tm unable to handle date value of " << d; + throw std::out_of_range(ss.str()); +#endif // USE_DATE_TIME_PRE_1_33_FACET_IO } tm datetm; boost::gregorian::date::ymd_type ymd = d.year_month_day(); diff --git a/include/boost/date_time/gregorian/formatters.hpp b/include/boost/date_time/gregorian/formatters.hpp index b0054dc..99992b8 100644 --- a/include/boost/date_time/gregorian/formatters.hpp +++ b/include/boost/date_time/gregorian/formatters.hpp @@ -11,7 +11,6 @@ #include "boost/date_time/compiler_config.hpp" #include "boost/date_time/gregorian/gregorian_types.hpp" -#include "boost/date_time/gregorian/greg_facet.hpp" #if defined(BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS) #include "boost/date_time/date_formatting_limited.hpp" #else diff --git a/include/boost/date_time/gregorian/formatters_limited.hpp b/include/boost/date_time/gregorian/formatters_limited.hpp index a5a4f8a..ecf4cbf 100644 --- a/include/boost/date_time/gregorian/formatters_limited.hpp +++ b/include/boost/date_time/gregorian/formatters_limited.hpp @@ -10,7 +10,6 @@ */ #include "boost/date_time/gregorian/gregorian_types.hpp" -#include "boost/date_time/gregorian/greg_facet.hpp" #include "boost/date_time/date_formatting_limited.hpp" #include "boost/date_time/iso_format.hpp" #include "boost/date_time/date_format_simple.hpp" diff --git a/include/boost/date_time/gregorian/greg_facet.hpp b/include/boost/date_time/gregorian/greg_facet.hpp index 4576e81..cda6203 100644 --- a/include/boost/date_time/gregorian/greg_facet.hpp +++ b/include/boost/date_time/gregorian/greg_facet.hpp @@ -31,6 +31,7 @@ namespace gregorian { typedef boost::date_time::weekdays weekday_enum; }; +#if defined(USE_DATE_TIME_PRE_1_33_FACET_IO) //! Create the base facet type for gregorian::date typedef boost::date_time::date_names_put greg_base_facet; @@ -199,7 +200,7 @@ namespace gregorian { os << fkb.day_of_week() << " before"; return os; } - +#endif // USE_DATE_TIME_PRE_1_33_FACET_IO /**************** Input Streaming ******************/ #if !defined(BOOST_NO_STD_ITERATOR_TRAITS) diff --git a/include/boost/date_time/gregorian/gregorian.hpp b/include/boost/date_time/gregorian/gregorian.hpp index fcabfd8..f10aac0 100644 --- a/include/boost/date_time/gregorian/gregorian.hpp +++ b/include/boost/date_time/gregorian/gregorian.hpp @@ -24,7 +24,13 @@ #else #include "boost/date_time/gregorian/formatters.hpp" #endif + +#if defined(USE_DATE_TIME_PRE_1_33_FACET_IO) #include "boost/date_time/gregorian/greg_facet.hpp" +#else +#include "boost/date_time/gregorian/gregorian_io.hpp" +#endif // USE_DATE_TIME_PRE_1_33_FACET_IO + #include "boost/date_time/gregorian/parsers.hpp" diff --git a/include/boost/date_time/gregorian/gregorian_io.hpp b/include/boost/date_time/gregorian/gregorian_io.hpp new file mode 100644 index 0000000..0ce44bd --- /dev/null +++ b/include/boost/date_time/gregorian/gregorian_io.hpp @@ -0,0 +1,249 @@ +#ifndef DATE_TIME_GREGORIAN_IO_HPP__ +#define DATE_TIME_GREGORIAN_IO_HPP__ + +/* Copyright (c) 2004 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) + * Author: Jeff Garland, Bart Garst + * $Date$ + */ + +#include "boost/date_time/date_facet.hpp" +#include "boost/date_time/period_formatter.hpp" +#include +#include + +namespace boost { +namespace gregorian { + + + typedef boost::date_time::period_formatter wperiod_formatter; + typedef boost::date_time::period_formatter period_formatter; + + typedef boost::date_time::date_facet wdate_facet; + typedef boost::date_time::date_facet date_facet; + + + template + inline std::basic_ostream& + operator<<(std::basic_ostream& os, const boost::gregorian::date& d) { + typedef boost::date_time::date_facet custom_date_facet; + typedef std::time_put std_date_facet; + std::ostreambuf_iterator oitr(os); + if (std::has_facet(os.getloc())) + std::use_facet(os.getloc()).put(oitr, os, os.fill(), d); + else { + //instantiate a custom facet for dealing with dates since the user + //has not put one in the stream so far. This is for efficiency + //since we would always need to reconstruct for every date + //if the locale did not already exist. Of course this will be overridden + //if the user imbues at some later point. With the default settings + //for the facet the resulting format will be the same as the + //std::time_facet settings. + std::ostreambuf_iterator oitr(os); + custom_date_facet* f = new custom_date_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(oitr, os, os.fill(), d); + } + return os; + } + + + template + inline + std::basic_ostream& + operator<<(std::basic_ostream& os, const date_duration& dd) + { + os << dd.get_rep(); + return os; + } + + + template + inline std::basic_ostream& + operator<<(std::basic_ostream& os, const boost::gregorian::date_period& dp) { + typedef boost::date_time::date_facet custom_date_facet; + typedef std::time_put std_date_facet; + std::ostreambuf_iterator oitr(os); + if (std::has_facet(os.getloc())) + std::use_facet(os.getloc()).put(oitr, os, os.fill(), dp); + else { + //instantiate a custom facet for dealing with date periods since the user + //has not put one in the stream so far. This is for efficiency + //since we would always need to reconstruct for every time period + //if the local did not already exist. Of course this will be overridden + //if the user imbues at some later point. With the default settings + //for the facet the resulting format will be the same as the + //std::time_facet settings. + std::ostreambuf_iterator oitr(os); + custom_date_facet* f = new custom_date_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(oitr, os, os.fill(), dp); + + } + return os; + } + + /********** small gregorian types **********/ + + template + inline std::basic_ostream& + operator<<(std::basic_ostream& os, const boost::gregorian::greg_month& gm) { + typedef boost::date_time::date_facet custom_date_facet; + typedef std::time_put std_date_facet; + std::ostreambuf_iterator oitr(os); + if (std::has_facet(os.getloc())) + std::use_facet(os.getloc()).put(oitr, os, os.fill(), gm); + else { + std::ostreambuf_iterator oitr(os); + custom_date_facet* f = new custom_date_facet();//-> 10/1074199752/32 because year & day not initialized in put(...) + //custom_date_facet* f = new custom_date_facet("%B"); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(oitr, os, os.fill(), gm); + } + return os; + } + + + template + inline std::basic_ostream& + operator<<(std::basic_ostream& os, const boost::gregorian::greg_weekday& gw) { + typedef boost::date_time::date_facet custom_date_facet; + typedef std::time_put std_date_facet; + std::ostreambuf_iterator oitr(os); + if (std::has_facet(os.getloc())) + std::use_facet(os.getloc()).put(oitr, os, os.fill(), gw); + else { + std::ostreambuf_iterator oitr(os); + custom_date_facet* f = new custom_date_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(oitr, os, os.fill(), gw); + } + return os; + } + + /********** date generator types **********/ + + template + inline std::basic_ostream& + operator<<(std::basic_ostream& os, const boost::gregorian::partial_date& pd) { + typedef boost::date_time::date_facet custom_date_facet; + typedef std::time_put std_date_facet; + std::ostreambuf_iterator oitr(os); + if (std::has_facet(os.getloc())) + std::use_facet(os.getloc()).put(oitr, os, os.fill(), pd); + else { + std::ostreambuf_iterator oitr(os); + custom_date_facet* f = new custom_date_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(oitr, os, os.fill(), pd); + } + return os; + } + + template + inline std::basic_ostream& + operator<<(std::basic_ostream& os, const boost::gregorian::nth_day_of_the_week_in_month& nkd) { + typedef boost::date_time::date_facet custom_date_facet; + typedef std::time_put std_date_facet; + std::ostreambuf_iterator oitr(os); + if (std::has_facet(os.getloc())) + std::use_facet(os.getloc()).put(oitr, os, os.fill(), nkd); + else { + std::ostreambuf_iterator oitr(os); + custom_date_facet* f = new custom_date_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(oitr, os, os.fill(), nkd); + } + return os; + } + + + template + inline std::basic_ostream& + operator<<(std::basic_ostream& os, const boost::gregorian::first_day_of_the_week_in_month& fkd) { + typedef boost::date_time::date_facet custom_date_facet; + typedef std::time_put std_date_facet; + std::ostreambuf_iterator oitr(os); + if (std::has_facet(os.getloc())) + std::use_facet(os.getloc()).put(oitr, os, os.fill(), fkd); + else { + std::ostreambuf_iterator oitr(os); + custom_date_facet* f = new custom_date_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(oitr, os, os.fill(), fkd); + } + return os; + } + + + template + inline std::basic_ostream& + operator<<(std::basic_ostream& os, const boost::gregorian::last_day_of_the_week_in_month& lkd) { + typedef boost::date_time::date_facet custom_date_facet; + typedef std::time_put std_date_facet; + std::ostreambuf_iterator oitr(os); + if (std::has_facet(os.getloc())) + std::use_facet(os.getloc()).put(oitr, os, os.fill(), lkd); + else { + std::ostreambuf_iterator oitr(os); + custom_date_facet* f = new custom_date_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(oitr, os, os.fill(), lkd); + } + return os; + } + + + template + inline std::basic_ostream& + operator<<(std::basic_ostream& os, const boost::gregorian::first_day_of_the_week_after& fda) { + typedef boost::date_time::date_facet custom_date_facet; + typedef std::time_put std_date_facet; + std::ostreambuf_iterator oitr(os); + if (std::has_facet(os.getloc())) { + std::use_facet(os.getloc()).put(oitr, os, os.fill(), fda); + } + else { + std::ostreambuf_iterator oitr(os); + custom_date_facet* f = new custom_date_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(oitr, os, os.fill(), fda); + } + return os; + } + + + template + inline std::basic_ostream& + operator<<(std::basic_ostream& os, const boost::gregorian::first_day_of_the_week_before& fdb) { + typedef boost::date_time::date_facet custom_date_facet; + typedef std::time_put std_date_facet; + std::ostreambuf_iterator oitr(os); + if (std::has_facet(os.getloc())) { + std::use_facet(os.getloc()).put(oitr, os, os.fill(), fdb); + } + else { + std::ostreambuf_iterator oitr(os); + custom_date_facet* f = new custom_date_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(oitr, os, os.fill(), fdb); + } + return os; + } + + +} } // namespaces + +#endif // DATE_TIME_GREGORIAN_IO_HPP__ diff --git a/include/boost/date_time/local_time/local_date_time.hpp b/include/boost/date_time/local_time/local_date_time.hpp index 962e766..226121d 100644 --- a/include/boost/date_time/local_time/local_date_time.hpp +++ b/include/boost/date_time/local_time/local_date_time.hpp @@ -27,15 +27,15 @@ namespace local_time { ambiguous_result (std::string _msg="") : std::logic_error(std::string("Daylight Savings Results are ambiguous: " + _msg)) {} }; - // - struct InvalidTimeLabel : public std::logic_error + //! simple exception for when time label given cannot exist + struct time_label_invalid : public std::logic_error { - InvalidTimeLabel(std::string _msg="") : + time_label_invalid (std::string _msg="") : std::logic_error(std::string("Time label given is invalid: " + _msg)) {} }; - struct DSTNotValid: public std::logic_error + struct dst_not_valid: public std::logic_error { - DSTNotValid(std::string _msg="") : + dst_not_valid(std::string _msg="") : std::logic_error(std::string("is_dst flag does not match resulting dst for time label given: " + _msg)) {} }; @@ -46,7 +46,16 @@ namespace local_time { using date_time::is_not_in_dst; using date_time::ambiguous; using date_time::invalid_time_label; - + + //! Representation of "wall-clock" time in a particular time zone + /*! Representation of "wall-clock" time in a particular time zone + * Local_date_time_base holds a time value (date and time offset from 00:00) + * along with a time zone. The time value is stored as UTC and conversions + * to wall clock time are made as needed. This approach allows for + * operations between wall-clock times in different time zones, and + * daylight savings time considerations, to be made. Time zones are + * required to be in the form of a boost::shared_ptr. + */ template > class local_date_time_base : public date_time::base_time zone() const { return zone_; @@ -299,30 +310,73 @@ namespace local_time { { return local_date_time_base(utc_time_type(time_) + td, new_tz); } + //! Returns name of associated time zone or "Coordinated Universal Time". - std::string zone_name() const + /*! Optional bool parameter will return time zone as an offset + * (ie "+07:00" extended iso format). Empty string is returned for + * classes that do not use a time_zone */ + std::string zone_name(bool as_offset=false) const { if(zone_ == NULL) { - return std::string("Coordinated Universal Time"); + if(as_offset) { + return std::string("Z"); + } + else { + return std::string("Coordinated Universal Time"); + } } if (is_dst()) { - return zone_->dst_zone_name(); + if(as_offset) { + time_duration_type td = zone_->base_utc_offset(); + td += zone_->dst_offset(); + return zone_as_offset(td, ":"); + } + else { + return zone_->dst_zone_name(); + } } else { - return zone_->std_zone_name(); + if(as_offset) { + time_duration_type td = zone_->base_utc_offset(); + return zone_as_offset(td, ":"); + } + else { + return zone_->std_zone_name(); + } } } - //! Returns abreviation of associated time zone or "UTC". - std::string zone_abbrev() const + //! Returns abbreviation of associated time zone or "UTC". + /*! Optional bool parameter will return time zone as an offset + * (ie "+0700" iso format). Empty string is returned for classes + * that do not use a time_zone */ + std::string zone_abbrev(bool as_offset=false) const { if(zone_ == NULL) { - return std::string("UTC"); + if(as_offset) { + return std::string("Z"); + } + else { + return std::string("UTC"); + } } if (is_dst()) { - return zone_->dst_zone_abbrev(); + if(as_offset) { + time_duration_type td = zone_->base_utc_offset(); + td += zone_->dst_offset(); + return zone_as_offset(td, ""); + } + else { + return zone_->dst_zone_abbrev(); + } } else { - return zone_->std_zone_abbrev(); + if(as_offset) { + time_duration_type td = zone_->base_utc_offset(); + return zone_as_offset(td, ""); + } + else { + return zone_->std_zone_abbrev(); + } } } @@ -425,6 +479,32 @@ namespace local_time { } return t; } + + std::string zone_as_offset(const time_duration_type& td, + const std::string& separator) const + { + // time_duration op<< uses the ptime facet. If we want to change + // its format we must use a time_facet + typedef boost::date_time::time_facet timefacet; + timefacet* facet_ptr = new timefacet(); + std::stringstream ss; + // build the format first + ss << "%H" << separator << "%M"; + facet_ptr->time_duration_format(ss.str().c_str()); + ss.str(""); + std::locale loc(std::locale::classic(), facet_ptr); + ss.imbue(loc); + if(td.is_negative()) { + // a negative duration is represented as "-[h]h:mm" + // we require two digits for the hour. A positive duration + // with the %H flag will always give two digits + ss << "-" << td.invert_sign(); + } + else { + ss << "+" << td; + } + return ss.str(); + } }; //!Use the default parameters to define local_date_time diff --git a/include/boost/date_time/local_time/posix_time_zone.hpp b/include/boost/date_time/local_time/posix_time_zone.hpp index 907c708..b5f5302 100644 --- a/include/boost/date_time/local_time/posix_time_zone.hpp +++ b/include/boost/date_time/local_time/posix_time_zone.hpp @@ -37,16 +37,16 @@ namespace local_time{ typedef boost::date_time::time_zone_base time_zone_base; //! A time zone class constructed from a POSIX time zone string - /*! A POSIX time zone string takes to form of:
+ /*! A POSIX time zone string takes the form of:
* "std offset dst [offset],start[/time],end[/time]" (w/no spaces) * 'std' specifies the abbrev of the time zone.
* 'offset' is the offset from UTC.
* 'dst' specifies the abbrev of the time zone during daylight savings time.
* The second offset is how many hours changed during DST. Default=1
- * 'start' & 'end' are the dates when DST goes into (and out of) effect.
+ * 'start' and'end' are the dates when DST goes into (and out of) effect.
* 'offset' takes the form of: [+|-]hh[:mm[:ss]] {h=0-23, m/s=0-59}
* 'time' and 'offset' take the same form. Time defaults=02:00:00
- * 'start' & 'end' can be one of three forms:
+ * 'start' and 'end' can be one of three forms:
* Mm.w.d {month=1-12, week=1-5 (5 is always last), day=0-6}
* Jn {n=1-365 Feb29 is never counted}
* n {n=0-365 Feb29 is counted in leap years}
@@ -173,16 +173,16 @@ namespace local_time{ // get duration while(!isalpha(*sit) && sit != obj.end()){ ss << *sit++; - } - base_utc_offset_ = posix_time::duration_from_string(ss.str()); - ss.str(""); + } + base_utc_offset_ = posix_time::duration_from_string(ss.str()); + ss.str(""); - // base offset must be within range of -12 hours to +12 hours - if(base_utc_offset_ < time_duration_type(-12,0,0) || - base_utc_offset_ > time_duration_type(12,0,0)) - { - throw bad_offset(posix_time::to_simple_string(base_utc_offset_)); - } + // base offset must be within range of -12 hours to +12 hours + if(base_utc_offset_ < time_duration_type(-12,0,0) || + base_utc_offset_ > time_duration_type(12,0,0)) + { + throw bad_offset(posix_time::to_simple_string(base_utc_offset_)); + } } // get DST data if given @@ -210,12 +210,12 @@ namespace local_time{ dst_offsets_.dst_adjust_ = posix_time::hours(1); } - // adjustment must be within +|- 1 day - if(dst_offsets_.dst_adjust_ <= time_duration_type(-24,0,0) || - dst_offsets_.dst_adjust_ >= time_duration_type(24,0,0)) - { - throw bad_adjustment(posix_time::to_simple_string(dst_offsets_.dst_adjust_)); - } + // adjustment must be within +|- 1 day + if(dst_offsets_.dst_adjust_ <= time_duration_type(-24,0,0) || + dst_offsets_.dst_adjust_ >= time_duration_type(24,0,0)) + { + throw bad_adjustment(posix_time::to_simple_string(dst_offsets_.dst_adjust_)); + } } // full names not extracted so abbrevs used in their place zone_names_ = time_zone_names(std_zone_abbrev, std_zone_abbrev, dst_zone_abbrev, dst_zone_abbrev); @@ -316,7 +316,7 @@ namespace local_time{ } int em=1, ed=0; ed = lexical_cast(e.substr(1)); // skip 'J' - while(ed >= calendar::end_of_month_day(year,em)){ + while(ed > calendar::end_of_month_day(year,em)){ ed -= calendar::end_of_month_day(year,em++); } @@ -344,6 +344,19 @@ namespace local_time{ ); } + //! helper function used when throwing exceptions + static std::string td_as_string(const time_duration_type& td) + { + std::string s; +#if defined(USE_DATE_TIME_PRE_1_33_FACET_IO) + s = posix_time::to_simple_string(td); +#else + std::stringstream ss; + ss << td; + s = ss.str(); +#endif + return s; + } }; } } // namespace boost::local_time diff --git a/include/boost/date_time/posix_time/conversion.hpp b/include/boost/date_time/posix_time/conversion.hpp index aa7345f..084fa0d 100644 --- a/include/boost/date_time/posix_time/conversion.hpp +++ b/include/boost/date_time/posix_time/conversion.hpp @@ -1,7 +1,7 @@ #ifndef POSIX_TIME_CONVERSION_HPP___ #define POSIX_TIME_CONVERSION_HPP___ -/* Copyright (c) 2002,2003 CrystalClear Software, Inc. +/* Copyright (c) 2002-2005 CrystalClear Software, Inc. * Use, modification and distribution is subject to the * Boost Software License, Version 1.0. (See accompanying * file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) @@ -35,7 +35,23 @@ namespace posix_time { timetm.tm_hour = td.hours(); timetm.tm_min = td.minutes(); timetm.tm_sec = td.seconds(); - timetm.tm_isdst = -1; //? + timetm.tm_isdst = -1; // -1 used when dst info is unknown + return timetm; + } + //! Convert a time_duration to a tm structure truncating any fractional seconds and zeroing fields for date components + inline + tm to_tm(const boost::posix_time::time_duration& td) { + tm timetm; + timetm.tm_year = 0; + timetm.tm_mon = 0; + timetm.tm_mday = 0; + timetm.tm_wday = 0; + timetm.tm_yday = 0; + + timetm.tm_hour = td.hours(); + timetm.tm_min = td.minutes(); + timetm.tm_sec = td.seconds(); + timetm.tm_isdst = -1; // -1 used when dst info is unknown return timetm; } diff --git a/include/boost/date_time/posix_time/posix_time.hpp b/include/boost/date_time/posix_time/posix_time.hpp index ffa65d4..a1642f2 100644 --- a/include/boost/date_time/posix_time/posix_time.hpp +++ b/include/boost/date_time/posix_time/posix_time.hpp @@ -1,7 +1,7 @@ #ifndef POSIX_TIME_HPP___ #define POSIX_TIME_HPP___ -/* Copyright (c) 2002-2004 CrystalClear Software, Inc. +/* Copyright (c) 2002-2005 CrystalClear Software, Inc. * Use, modification and distribution is subject to the * Boost Software License, Version 1.0. (See accompanying * file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) @@ -16,11 +16,21 @@ #if defined(BOOST_DATE_TIME_OPTIONAL_GREGORIAN_TYPES) #include "boost/date_time/posix_time/date_duration_operators.hpp" #endif + +// output functions #if defined(BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS) #include "boost/date_time/posix_time/time_formatters_limited.hpp" #else #include "boost/date_time/posix_time/time_formatters.hpp" -#endif +#endif // BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS + +// streaming operators +#if defined(USE_DATE_TIME_PRE_1_33_FACET_IO) +#include "boost/date_time/posix_time/posix_time_legacy_io.hpp" +#else +#include "boost/date_time/posix_time/posix_time_io.hpp" +#endif // USE_DATE_TIME_PRE_1_33_FACET_IO + #include "boost/date_time/posix_time/time_parsers.hpp" #include "boost/date_time/posix_time/conversion.hpp" diff --git a/include/boost/date_time/posix_time/posix_time_io.hpp b/include/boost/date_time/posix_time/posix_time_io.hpp new file mode 100644 index 0000000..8b93d01 --- /dev/null +++ b/include/boost/date_time/posix_time/posix_time_io.hpp @@ -0,0 +1,117 @@ +#ifndef DATE_TIME_POSIX_TIME_IO_HPP__ +#define DATE_TIME_POSIX_TIME_IO_HPP__ + +/* Copyright (c) 2004-2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) + * Author: Jeff Garland, Bart Garst + * $Date$ + */ + +#include "boost/date_time/time_facet.hpp" +#include "boost/date_time/period_formatter.hpp" +#include "boost/date_time/posix_time/time_period.hpp" +#include "boost/date_time/posix_time/posix_time_duration.hpp" +//#include "boost/date_time/gregorian/gregorian_io.hpp" +#include +#include + +namespace boost { +namespace posix_time { + + + typedef boost::date_time::time_facet wptime_facet; + typedef boost::date_time::time_facet ptime_facet; + + + template + inline + std::basic_ostream& + operator<<(std::basic_ostream& os, + const ptime& p) { + typedef boost::date_time::time_facet custom_ptime_facet; + typedef std::time_put std_ptime_facet; + std::ostreambuf_iterator oitr(os); + if (std::has_facet(os.getloc())) + std::use_facet(os.getloc()).put(oitr, os, os.fill(), p); + else { + //instantiate a custom facet for dealing with times since the user + //has not put one in the stream so far. This is for efficiency + //since we would always need to reconstruct for every time period + //if the locale did not already exist. Of course this will be overridden + //if the user imbues as some later point. + std::ostreambuf_iterator oitr(os); + custom_ptime_facet* f = new custom_ptime_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(oitr, os, os.fill(), p); + } + return os; + } + + template + inline + std::basic_ostream& + operator<<(std::basic_ostream& os, + const boost::posix_time::time_period& p) { + typedef boost::date_time::time_facet custom_ptime_facet; + typedef std::time_put std_time_facet; + std::ostreambuf_iterator oitr(os); + if (std::has_facet(os.getloc())) { + std::use_facet(os.getloc()).put(oitr, os, os.fill(), p); + } + else { + //instantiate a custom facet for dealing with periods since the user + //has not put one in the stream so far. This is for efficiency + //since we would always need to reconstruct for every time period + //if the local did not already exist. Of course this will be overridden + //if the user imbues as some later point. + std::ostreambuf_iterator oitr(os); + custom_ptime_facet* f = new custom_ptime_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(oitr, os, os.fill(), p); + } + return os; + } + + + //! ostream operator for posix_time::time_duration + // todo fix to use facet -- place holder for now... + template + inline + std::basic_ostream& + operator<<(std::basic_ostream& os, const time_duration& td) + { + typedef boost::date_time::time_facet custom_ptime_facet; + typedef std::time_put std_ptime_facet; + std::ostreambuf_iterator oitr(os); + if (std::has_facet(os.getloc())) + std::use_facet(os.getloc()).put(oitr, os, os.fill(), td); + else { + //instantiate a custom facet for dealing with times since the user + //has not put one in the stream so far. This is for efficiency + //since we would always need to reconstruct for every time period + //if the locale did not already exist. Of course this will be overridden + //if the user imbues as some later point. + std::ostreambuf_iterator oitr(os); + // TODO create a default time_duration format + //const CharT fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 's', '\0'}; + custom_ptime_facet* f = new custom_ptime_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(oitr, os, os.fill(), td); + } + return os; + /* + typedef boost::date_time::ostream_time_duration_formatter duration_formatter; + duration_formatter::duration_put(td, os); + return os; + */ + } + + + +} } // namespaces +#endif // DATE_TIME_POSIX_TIME_IO_HPP__ diff --git a/include/boost/date_time/posix_time/time_formatters.hpp b/include/boost/date_time/posix_time/time_formatters.hpp index 39a68a9..e212811 100644 --- a/include/boost/date_time/posix_time/time_formatters.hpp +++ b/include/boost/date_time/posix_time/time_formatters.hpp @@ -282,130 +282,6 @@ namespace posix_time { #endif // BOOST_NO_STD_WSTRING - /* ATTENTION: The following operator<< functions are exactly duplicated - * in time_formatters_limited.hpp. Any changes here must also be made there - */ - -//The following code is removed for configurations with good std::locale support (eg: MSVC6, gcc 2.9x) -#ifndef BOOST_DATE_TIME_NO_LOCALE - - //! ostream operator for posix_time::time_duration - template - inline - std::basic_ostream& - operator<<(std::basic_ostream& os, const time_duration& td) - { - typedef boost::date_time::ostream_time_duration_formatter duration_formatter; - duration_formatter::duration_put(td, os); - return os; - } - - //! ostream operator for posix_time::ptime - template - inline - std::basic_ostream& - operator<<(std::basic_ostream& os, const ptime& t) - { - typedef boost::date_time::ostream_time_formatter time_formatter; - time_formatter::time_put(t, os); - return os; - } - - //! ostream operator for posix_time::time_period - template - inline - std::basic_ostream& - operator<<(std::basic_ostream& os, const time_period& tp) - { - typedef boost::date_time::ostream_time_period_formatter period_formatter; - period_formatter::period_put(tp, os); - return os; - } - -/******** input streaming ********/ - template - inline - std::basic_istream& operator>>(std::basic_istream& is, time_duration& td) - { - // need to create a std::string and parse it - std::basic_string inp_s; - std::stringstream out_ss; - is >> inp_s; - typename std::basic_string::iterator b = inp_s.begin(); - // need to use both iterators because there is no requirement - // for the data held by a std::basic_string<> be terminated with - // any marker (such as '\0'). - typename std::basic_string::iterator e = inp_s.end(); - while(b != e){ - out_ss << out_ss.narrow(*b, 0); - ++b; - } - - td = date_time::parse_delimited_time_duration(out_ss.str()); - return is; - } - - template - inline - std::basic_istream& operator>>(std::basic_istream& is, ptime& pt) - { - gregorian::date d(not_a_date_time); - time_duration td(0,0,0); - is >> d >> td; - pt = ptime(d, td); - - return is; - } - - /** operator>> for time_period. time_period must be in - * "[date time_duration/date time_duration]" format. */ - template - inline - std::basic_istream& operator>>(std::basic_istream& is, time_period& tp) - { - gregorian::date d(not_a_date_time); - time_duration td(0,0,0); - ptime beg(d, td); - ptime end(beg); - std::basic_string s; - // get first date string and remove leading '[' - is >> s; - { - std::basic_stringstream ss; - ss << s.substr(s.find('[')+1); - ss >> d; - } - // get first time_duration & second date string, remove the '/' - // and split into 2 strings - is >> s; - { - std::basic_stringstream ss; - ss << s.substr(0, s.find('/')); - ss >> td; - } - beg = ptime(d, td); - { - std::basic_stringstream ss; - ss << s.substr(s.find('/')+1); - ss >> d; - } - // get last time_duration and remove the trailing ']' - is >> s; - { - std::basic_stringstream ss; - ss << s.substr(0, s.find(']')); - ss >> td; - } - end = ptime(d, td); - - tp = time_period(beg,end); - return is; - } - - -#endif //BOOST_DATE_TIME_NO_LOCALE - - } } //namespace posix_time diff --git a/include/boost/date_time/posix_time/time_formatters_limited.hpp b/include/boost/date_time/posix_time/time_formatters_limited.hpp index 153eb26..d926508 100644 --- a/include/boost/date_time/posix_time/time_formatters_limited.hpp +++ b/include/boost/date_time/posix_time/time_formatters_limited.hpp @@ -204,51 +204,6 @@ namespace posix_time { } - /* ATTENTION: The following operator<< functions are exactly duplicated - * in time_formatters.hpp. Any changes here must also be made there - */ - -//The following code is removed for configurations with good std::locale support (eg: MSVC6, gcc 2.9x) -#ifndef BOOST_DATE_TIME_NO_LOCALE - - //! ostream operator for posix_time::time_duration - template - inline - std::basic_ostream& - operator<<(std::basic_ostream& os, const time_duration& td) - { - typedef boost::date_time::ostream_time_duration_formatter duration_formatter; - duration_formatter::duration_put(td, os); - return os; - } - - //! ostream operator for posix_time::ptime - template - inline - std::basic_ostream& - operator<<(std::basic_ostream& os, const ptime& t) - { - typedef boost::date_time::ostream_time_formatter time_formatter; - time_formatter::time_put(t, os); - return os; - } - - //! ostream operator for posix_time::time_period - template - inline - std::basic_ostream& - operator<<(std::basic_ostream& os, const time_period& tp) - { - typedef boost::date_time::ostream_time_period_formatter period_formatter; - period_formatter::period_put(tp, os); - return os; - } - - - -#endif //BOOST_DATE_TIME_NO_LOCALE - - } } //namespace posix_time diff --git a/include/boost/date_time/strings_from_facet.hpp b/include/boost/date_time/strings_from_facet.hpp index d7f41ba..3b7283f 100644 --- a/include/boost/date_time/strings_from_facet.hpp +++ b/include/boost/date_time/strings_from_facet.hpp @@ -9,6 +9,11 @@ * $Date$ */ +#include +#include +#include +#include + namespace boost { namespace date_time { //! This function gathers up all the month strings from a std::locale diff --git a/include/boost/date_time/time.hpp b/include/boost/date_time/time.hpp index 26141b2..344d4b2 100644 --- a/include/boost/date_time/time.hpp +++ b/include/boost/date_time/time.hpp @@ -74,7 +74,17 @@ namespace date_time { { return time_system::get_time_of_day(time_); } - std::string zone_name() const + /*! Optional bool parameter will return time zone as an offset + * (ie "+07:00"). Empty string is returned for classes that do + * not use a time_zone */ + std::string zone_name(bool as_offset=false) const + { + return time_system::zone_name(time_); + } + /*! Optional bool parameter will return time zone as an offset + * (ie "+07:00"). Empty string is returned for classes that do + * not use a time_zone */ + std::string zone_abbrev(bool as_offset=false) const { return time_system::zone_name(time_); } diff --git a/include/boost/date_time/time_facet.hpp b/include/boost/date_time/time_facet.hpp index 9363442..0f1d1b0 100644 --- a/include/boost/date_time/time_facet.hpp +++ b/include/boost/date_time/time_facet.hpp @@ -11,6 +11,7 @@ */ #include "boost/date_time/date_facet.hpp" +#include namespace boost { namespace date_time { @@ -41,48 +42,68 @@ namespace date_time { typedef typename base_type::char_type char_type; typedef typename base_type::period_formatter_type period_formatter_type; typedef typename base_type::special_values_formatter_type special_values_formatter_type; + typedef typename base_type::date_gen_formatter_type date_gen_formatter_type; static const char_type fractional_seconds_format[3]; // f static const char_type fractional_seconds_or_none_format[3]; // F static const char_type seconds_with_fractional_seconds_format[3]; // s static const char_type seconds_format[3]; // S - // TODO: Our standard format currently includes a time sone abbreviation. - // we want it to be "+|-hh:mm" static const char_type standard_format[5]; // c static const char_type zone_abbrev_format[3]; // z static const char_type zone_name_format[3]; // Z + static const char_type zone_iso_format[3]; // q + static const char_type zone_iso_extended_format[3]; // Q + //static const char_type duration_sign_specifier[3]; // # static const char_type duration_seperator[2]; - static const char_type iso_time_format_specifier[16]; - static const char_type iso_time_format_extended_specifier[20]; - static std::locale::id id; - + static const char_type iso_time_format_specifier[18]; + static const char_type iso_time_format_extended_specifier[22]; + // TODO: Our standard format currently includes a time zone abbreviation. + // we want it to be "+|-hh:mm" + //default ptime format is YYYY-Mon-DD HH:MM:SS[.fff...][ zzz] + static const char_type default_time_format[23]; + //default time_duration format is HH:MM:SS[.fff...] + static const char_type default_time_duration_format[11]; + static std::locale::id id; + + //! sets default formats for ptime, local_date_time, and time_duration explicit time_facet(::size_t a_ref = 0) - : base_type(standard_format), + //: base_type(standard_format), + : base_type(default_time_format), + m_time_duration_format(default_time_duration_format), m_time_duration_seperator(duration_seperator) { set_duration_seperator_from_facet(); //todo fix this } + //TODO sets time_dur to default - change to a custom? explicit time_facet(const char_type* a_format, period_formatter_type period_formatter = period_formatter_type(), const special_values_formatter_type& special_value_formatter = special_values_formatter_type(), + date_gen_formatter_type dg_formatter = date_gen_formatter_type(), ::size_t a_ref = 0) : base_type(a_format, period_formatter, special_value_formatter, + dg_formatter, a_ref), + m_time_duration_format(default_time_duration_format), m_time_duration_seperator(duration_seperator) {} - + //! Changes format for time_duration + void time_duration_format(const char_type* const format) { + m_time_duration_format = format; + } virtual void set_iso_format() { m_format = iso_time_format_specifier; + //TODO: set time_dur format to iso spec too? } virtual void set_iso_extended_format() { m_format = iso_time_format_extended_specifier; + //TODO: set time_dur format to iso_ext spec too? } OutItrT put(OutItrT a_next, @@ -110,14 +131,80 @@ namespace date_time { replace_string); } if (format.find(zone_name_format)) { - boost::algorithm::replace_all(format, - zone_name_format, - a_time.zone_name()); + if(a_time.zone_name().empty()) { + /* TODO: this'll probably create problems if a user places + * the zone_*_format flag in the format with a ptime. This + * code removes the flag from the default formats */ + + // if zone_name() returns an empty string, we want to + // erase zone_name_format & one preceeding space + std::basic_stringstream ss; + ss << ' ' << zone_name_format; + boost::algorithm::replace_all(format, + ss.str(), + ""); + } + else{ + boost::algorithm::replace_all(format, + zone_name_format, + a_time.zone_name()); + } } if (format.find(zone_abbrev_format)) { - boost::algorithm::replace_all(format, - zone_abbrev_format, - a_time.zone_abbrev()); + if(a_time.zone_abbrev(false).empty()) { + /* TODO: this'll probably create problems if a user places + * the zone_*_format flag in the format with a ptime. This + * code removes the flag from the default formats */ + + // if zone_abbrev() returns an empty string, we want to + // erase zone_abbrev_format & one preceeding space + std::basic_stringstream ss; + ss << ' ' << zone_abbrev_format; + boost::algorithm::replace_all(format, + ss.str(), + ""); + } + else{ + boost::algorithm::replace_all(format, + zone_abbrev_format, + a_time.zone_abbrev(false)); + } + } + if (format.find(zone_iso_extended_format)) { + if(a_time.zone_name(true).empty()) { + /* TODO: this'll probably create problems if a user places + * the zone_*_format flag in the format with a ptime. This + * code removes the flag from the default formats */ + + // if zone_name() returns an empty string, we want to + // erase zone_iso_extended_format from format + boost::algorithm::replace_all(format, + zone_iso_extended_format, + ""); + } + else{ + boost::algorithm::replace_all(format, + zone_iso_extended_format, + a_time.zone_name(true)); + } + } + if (format.find(zone_iso_format)) { + if(a_time.zone_abbrev(true).empty()) { + /* TODO: this'll probably create problems if a user places + * the zone_*_format flag in the format with a ptime. This + * code removes the flag from the default formats */ + + // if zone_abbrev() returns an empty string, we want to + // erase zone_iso_format from format + boost::algorithm::replace_all(format, + zone_iso_format, + ""); + } + else{ + boost::algorithm::replace_all(format, + zone_iso_format, + a_time.zone_abbrev(true)); + } } if (format.find(fractional_seconds_format)) { // replace %f with nnnnnnn @@ -148,12 +235,72 @@ namespace date_time { } } - // trim format before put to remove empty whitespace - boost::algorithm::trim(format); - return do_put_tm(a_next, a_ios, a_fill, to_tm(a_time), format); } + + //! put function for time_duration + OutItrT put(OutItrT a_next, + std::ios_base& a_ios, + char_type a_fill, + const time_duration_type& a_time_dur) const + { + /* TODO: Fix this + if (a_time_dur.is_special()) { + return do_put_special(a_next, a_ios, a_fill, + a_time_dur.date().as_special()); + } + */ + string_type format(m_time_duration_format); + string_type frac_str; + if (format.find(seconds_with_fractional_seconds_format)) { + // replace %s with %S.nnn + frac_str = + fractional_seconds_as_string(a_time_dur, false); + char_type sep = std::use_facet >(a_ios.getloc()).decimal_point(); + + string_type replace_string(seconds_format); + replace_string += sep; + replace_string += frac_str; + boost::algorithm::replace_all(format, + seconds_with_fractional_seconds_format, + replace_string); + } + if (format.find(fractional_seconds_format)) { + // replace %f with nnnnnnn + if (!frac_str.size()) { + frac_str = fractional_seconds_as_string(a_time_dur, false); + } + boost::algorithm::replace_all(format, + fractional_seconds_format, + frac_str); + } + + if (format.find(fractional_seconds_or_none_format)) { + // replace %F with nnnnnnn or nothing if fs == 0 + frac_str = + fractional_seconds_as_string(a_time_dur, true); + if (frac_str.size()) { + char_type sep = std::use_facet >(a_ios.getloc()).decimal_point(); + string_type replace_string; + replace_string += sep; + replace_string += frac_str; + boost::algorithm::replace_all(format, + fractional_seconds_or_none_format, + replace_string); + } + else { + boost::algorithm::erase_all(format, + fractional_seconds_or_none_format); + } + } + + // trim format before put to remove empty whitespace + //boost::algorithm::trim(format); + + return do_put_tm(a_next, a_ios, a_fill, + to_tm(a_time_dur), format); + } OutItrT put(OutItrT next, std::ios_base& a_ios, char_type fill, const period_type& p) const @@ -200,6 +347,7 @@ namespace date_time { { //todo write this function } + string_type m_time_duration_format; string_type m_time_duration_seperator; }; @@ -229,6 +377,14 @@ namespace date_time { const typename time_facet::char_type time_facet::zone_abbrev_format[3] = {'%','z'}; + template + const typename time_facet::char_type + time_facet::zone_iso_extended_format[3] ={'%','Q'}; + + template + const typename time_facet::char_type + time_facet::zone_iso_format[3] = {'%','q'}; + template const typename time_facet::char_type time_facet::seconds_format[3] = {'%','S'}; @@ -243,13 +399,26 @@ namespace date_time { template const typename time_facet::char_type - time_facet::iso_time_format_specifier[16] = - {'%', 'Y', '%', 'm', '%', 'd', 'T', '%', 'H', '%', 'M', '%', 'S', '%', 'F'}; + time_facet::iso_time_format_specifier[18] = + {'%', 'Y', '%', 'm', '%', 'd', 'T', + '%', 'H', '%', 'M', '%', 'S', '%', 'F', '%','q' }; template const typename time_facet::char_type - time_facet::iso_time_format_extended_specifier[20] = - {'%', 'Y', '-', '%', 'm', '-', '%', 'd', ' ', '%', 'H', ':', '%', 'M', ':', '%', 'S', '%', 'F'}; + time_facet::iso_time_format_extended_specifier[22] = + {'%', 'Y', '-', '%', 'm', '-', '%', 'd', ' ', + '%', 'H', ':', '%', 'M', ':', '%', 'S', '%', 'F','%','Q'}; + + template + const typename time_facet::char_type + time_facet::default_time_format[23] = + {'%','Y','-','%','b','-','%','d',' ', + '%','H',':','%','M',':','%','S','%','F',' ','%','z'}; + + template + const typename time_facet::char_type + time_facet::default_time_duration_format[11] = + {'%','H',':','%','M',':','%','S','%','F'}; } }