1 #ifndef _DATE_TIME_DATE_GENERATOR_FORMATTER__HPP___ 2 #define _DATE_TIME_DATE_GENERATOR_FORMATTER__HPP___ 3 4 /* Copyright (c) 2004 CrystalClear Software, Inc. 5 * Use, modification and distribution is subject to the 6 * Boost Software License, Version 1.0. (See accompanying 7 * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) 8 * Author: Jeff Garland, Bart Garst 9 * $Date$ 10 */ 11 12 #include <iostream> 13 #include <string> 14 #include <vector> 15 #include <algorithm> 16 #include "boost/date_time/date_generators.hpp" 17 18 namespace boost { 19 namespace date_time { 20 21 //! Formats date_generators for output 22 /*! Formatting of date_generators follows specific orders for the 23 * various types of date_generators. 24 * - partial_date => "dd Month" 25 * - nth_day_of_the_week_in_month => "nth weekday of month" 26 * - first_day_of_the_week_in_month => "first weekday of month" 27 * - last_day_of_the_week_in_month => "last weekday of month" 28 * - first_day_of_the_week_after => "weekday after" 29 * - first_day_of_the_week_before => "weekday before" 30 * While the order of the elements in these phrases cannot be changed, 31 * the elements themselves can be. Weekday and Month get their formats 32 * and names from the date_facet. The remaining elements are stored in 33 * the date_generator_formatter and can be customized upon construction 34 * or via a member function. The default elements are those shown in the 35 * examples above. 36 */ 37 template <class date_type, class CharT, class OutItrT = std::ostreambuf_iterator<CharT, std::char_traits<CharT> > > 38 class date_generator_formatter { 39 public: 40 typedef partial_date<date_type> partial_date_type; 41 typedef nth_kday_of_month<date_type> nth_kday_type; 42 typedef first_kday_of_month<date_type> first_kday_type; 43 typedef last_kday_of_month<date_type> last_kday_type; 44 typedef first_kday_after<date_type> kday_after_type; 45 typedef first_kday_before<date_type> kday_before_type; 46 47 typedef CharT char_type; 48 typedef std::basic_string<char_type> string_type; 49 typedef std::vector<string_type> collection_type; 50 static const char_type first_string[6]; 51 static const char_type second_string[7]; 52 static const char_type third_string[6]; 53 static const char_type fourth_string[7]; 54 static const char_type fifth_string[6]; 55 static const char_type last_string[5]; 56 static const char_type before_string[8]; 57 static const char_type after_string[6]; 58 static const char_type of_string[3]; 59 60 enum phrase_elements {first=0, second, third, fourth, fifth, last, 61 before, after, of, number_of_phrase_elements}; 62 63 //! Default format elements used date_generator_formatter()64 date_generator_formatter() 65 { 66 phrase_strings.reserve(number_of_phrase_elements); 67 phrase_strings.push_back(string_type(first_string)); 68 phrase_strings.push_back(string_type(second_string)); 69 phrase_strings.push_back(string_type(third_string)); 70 phrase_strings.push_back(string_type(fourth_string)); 71 phrase_strings.push_back(string_type(fifth_string)); 72 phrase_strings.push_back(string_type(last_string)); 73 phrase_strings.push_back(string_type(before_string)); 74 phrase_strings.push_back(string_type(after_string)); 75 phrase_strings.push_back(string_type(of_string)); 76 } 77 78 //! Constructor that allows for a custom set of phrase elements date_generator_formatter(const string_type & first_str,const string_type & second_str,const string_type & third_str,const string_type & fourth_str,const string_type & fifth_str,const string_type & last_str,const string_type & before_str,const string_type & after_str,const string_type & of_str)79 date_generator_formatter(const string_type& first_str, 80 const string_type& second_str, 81 const string_type& third_str, 82 const string_type& fourth_str, 83 const string_type& fifth_str, 84 const string_type& last_str, 85 const string_type& before_str, 86 const string_type& after_str, 87 const string_type& of_str) 88 { 89 phrase_strings.reserve(number_of_phrase_elements); 90 phrase_strings.push_back(first_str); 91 phrase_strings.push_back(second_str); 92 phrase_strings.push_back(third_str); 93 phrase_strings.push_back(fourth_str); 94 phrase_strings.push_back(fifth_str); 95 phrase_strings.push_back(last_str); 96 phrase_strings.push_back(before_str); 97 phrase_strings.push_back(after_str); 98 phrase_strings.push_back(of_str); 99 } 100 101 //! Replace the set of phrase elements with those contained in new_strings 102 /*! The order of the strings in the given collection is important. 103 * They must follow: 104 * - first, second, third, fourth, fifth, last, before, after, of. 105 * 106 * It is not necessary to send in a complete set if only a few 107 * elements are to be replaced as long as the correct beg_pos is used. 108 * 109 * Ex: To keep the default first through fifth elements, but replace 110 * the rest with a collection of: 111 * - "final", "prior", "following", "in". 112 * The beg_pos of date_generator_formatter::last would be used. 113 */ elements(const collection_type & new_strings,phrase_elements beg_pos=first)114 void elements(const collection_type& new_strings, 115 phrase_elements beg_pos=first) 116 { 117 if(beg_pos < number_of_phrase_elements) { 118 typename collection_type::iterator itr = phrase_strings.begin(); 119 itr += beg_pos; 120 std::copy(new_strings.begin(), new_strings.end(), 121 itr); 122 //phrase_strings.begin()); 123 } 124 } 125 126 //!Put a partial_date => "dd Month" 127 template<class facet_type> put_partial_date(OutItrT next,std::ios_base & a_ios,CharT a_fill,const partial_date_type & pd,const facet_type & facet) const128 OutItrT put_partial_date(OutItrT next, std::ios_base& a_ios, 129 CharT a_fill, const partial_date_type& pd, 130 const facet_type& facet) const 131 { 132 facet.put(next, a_ios, a_fill, pd.day()); 133 next = a_fill; //TODO change this ??? 134 facet.put(next, a_ios, a_fill, pd.month()); 135 return next; 136 } 137 138 //! Put an nth_day_of_the_week_in_month => "nth weekday of month" 139 template<class facet_type> put_nth_kday(OutItrT next,std::ios_base & a_ios,CharT a_fill,const nth_kday_type & nkd,const facet_type & facet) const140 OutItrT put_nth_kday(OutItrT next, std::ios_base& a_ios, 141 CharT a_fill, const nth_kday_type& nkd, 142 const facet_type& facet) const 143 { 144 put_string(next, phrase_strings[nkd.nth_week() -1]); 145 next = a_fill; //TODO change this ??? 146 facet.put(next, a_ios, a_fill, nkd.day_of_week()); 147 next = a_fill; //TODO change this ??? 148 put_string(next, string_type(of_string)); 149 next = a_fill; //TODO change this ??? 150 facet.put(next, a_ios, a_fill, nkd.month()); 151 return next; 152 } 153 154 //! Put a first_day_of_the_week_in_month => "first weekday of month" 155 template<class facet_type> put_first_kday(OutItrT next,std::ios_base & a_ios,CharT a_fill,const first_kday_type & fkd,const facet_type & facet) const156 OutItrT put_first_kday(OutItrT next, std::ios_base& a_ios, 157 CharT a_fill, const first_kday_type& fkd, 158 const facet_type& facet) const 159 { 160 put_string(next, phrase_strings[first]); 161 next = a_fill; //TODO change this ??? 162 facet.put(next, a_ios, a_fill, fkd.day_of_week()); 163 next = a_fill; //TODO change this ??? 164 put_string(next, string_type(of_string)); 165 next = a_fill; //TODO change this ??? 166 facet.put(next, a_ios, a_fill, fkd.month()); 167 return next; 168 } 169 170 //! Put a last_day_of_the_week_in_month => "last weekday of month" 171 template<class facet_type> put_last_kday(OutItrT next,std::ios_base & a_ios,CharT a_fill,const last_kday_type & lkd,const facet_type & facet) const172 OutItrT put_last_kday(OutItrT next, std::ios_base& a_ios, 173 CharT a_fill, const last_kday_type& lkd, 174 const facet_type& facet) const 175 { 176 put_string(next, phrase_strings[last]); 177 next = a_fill; //TODO change this ??? 178 facet.put(next, a_ios, a_fill, lkd.day_of_week()); 179 next = a_fill; //TODO change this ??? 180 put_string(next, string_type(of_string)); 181 next = a_fill; //TODO change this ??? 182 facet.put(next, a_ios, a_fill, lkd.month()); 183 return next; 184 } 185 186 //! Put a first_day_of_the_week_before => "weekday before" 187 template<class facet_type> put_kday_before(OutItrT next,std::ios_base & a_ios,CharT a_fill,const kday_before_type & fkb,const facet_type & facet) const188 OutItrT put_kday_before(OutItrT next, std::ios_base& a_ios, 189 CharT a_fill, const kday_before_type& fkb, 190 const facet_type& facet) const 191 { 192 facet.put(next, a_ios, a_fill, fkb.day_of_week()); 193 next = a_fill; //TODO change this ??? 194 put_string(next, phrase_strings[before]); 195 return next; 196 } 197 198 //! Put a first_day_of_the_week_after => "weekday after" 199 template<class facet_type> put_kday_after(OutItrT next,std::ios_base & a_ios,CharT a_fill,const kday_after_type & fka,const facet_type & facet) const200 OutItrT put_kday_after(OutItrT next, std::ios_base& a_ios, 201 CharT a_fill, const kday_after_type& fka, 202 const facet_type& facet) const 203 { 204 facet.put(next, a_ios, a_fill, fka.day_of_week()); 205 next = a_fill; //TODO change this ??? 206 put_string(next, phrase_strings[after]); 207 return next; 208 } 209 210 211 private: 212 collection_type phrase_strings; 213 214 //! helper function to put the various member string into stream put_string(OutItrT next,const string_type & str) const215 OutItrT put_string(OutItrT next, const string_type& str) const 216 { 217 typename string_type::const_iterator itr = str.begin(); 218 while(itr != str.end()) { 219 *next = *itr; 220 ++itr; 221 ++next; 222 } 223 return next; 224 } 225 }; 226 227 template<class date_type, class CharT, class OutItrT> 228 const typename date_generator_formatter<date_type, CharT, OutItrT>::char_type 229 date_generator_formatter<date_type, CharT, OutItrT>::first_string[6] = 230 {'f','i','r','s','t'}; 231 template<class date_type, class CharT, class OutItrT> 232 const typename date_generator_formatter<date_type, CharT, OutItrT>::char_type 233 date_generator_formatter<date_type, CharT, OutItrT>::second_string[7] = 234 {'s','e','c','o','n','d'}; 235 template<class date_type, class CharT, class OutItrT> 236 const typename date_generator_formatter<date_type, CharT, OutItrT>::char_type 237 date_generator_formatter<date_type, CharT, OutItrT>::third_string[6] = 238 {'t','h','i','r','d'}; 239 template<class date_type, class CharT, class OutItrT> 240 const typename date_generator_formatter<date_type, CharT, OutItrT>::char_type 241 date_generator_formatter<date_type, CharT, OutItrT>::fourth_string[7] = 242 {'f','o','u','r','t','h'}; 243 template<class date_type, class CharT, class OutItrT> 244 const typename date_generator_formatter<date_type, CharT, OutItrT>::char_type 245 date_generator_formatter<date_type, CharT, OutItrT>::fifth_string[6] = 246 {'f','i','f','t','h'}; 247 template<class date_type, class CharT, class OutItrT> 248 const typename date_generator_formatter<date_type, CharT, OutItrT>::char_type 249 date_generator_formatter<date_type, CharT, OutItrT>::last_string[5] = 250 {'l','a','s','t'}; 251 template<class date_type, class CharT, class OutItrT> 252 const typename date_generator_formatter<date_type, CharT, OutItrT>::char_type 253 date_generator_formatter<date_type, CharT, OutItrT>::before_string[8] = 254 {'b','e','f','o','r','e'}; 255 template<class date_type, class CharT, class OutItrT> 256 const typename date_generator_formatter<date_type, CharT, OutItrT>::char_type 257 date_generator_formatter<date_type, CharT, OutItrT>::after_string[6] = 258 {'a','f','t','e','r'}; 259 template<class date_type, class CharT, class OutItrT> 260 const typename date_generator_formatter<date_type, CharT, OutItrT>::char_type 261 date_generator_formatter<date_type, CharT, OutItrT>::of_string[3] = 262 {'o','f'}; 263 } } // namespaces 264 265 #endif // _DATE_TIME_DATE_GENERATOR_FORMATTER__HPP___ 266