date_generator_formatter.hpp 11 KB

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