adjust_functors.hpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. #ifndef _DATE_TIME_ADJUST_FUNCTORS_HPP___
  2. #define _DATE_TIME_ADJUST_FUNCTORS_HPP___
  3. /* Copyright (c) 2002,2003 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: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $
  9. */
  10. #include "boost/date_time/date.hpp"
  11. #include "boost/date_time/wrapping_int.hpp"
  12. namespace boost {
  13. namespace date_time {
  14. //! Functor to iterate a fixed number of days
  15. template<class date_type>
  16. class day_functor
  17. {
  18. public:
  19. typedef typename date_type::duration_type duration_type;
  20. day_functor(int f) : f_(f) {}
  21. duration_type get_offset(const date_type& d) const
  22. {
  23. // why is 'd' a parameter???
  24. // fix compiler warnings
  25. d.year();
  26. return duration_type(f_);
  27. }
  28. duration_type get_neg_offset(const date_type& d) const
  29. {
  30. // fix compiler warnings
  31. d.year();
  32. return duration_type(-f_);
  33. }
  34. private:
  35. int f_;
  36. };
  37. //! Provides calculation to find next nth month given a date
  38. /*! This adjustment function provides the logic for 'month-based'
  39. * advancement on a ymd based calendar. The policy it uses
  40. * to handle the non existant end of month days is to back
  41. * up to the last day of the month. Also, if the starting
  42. * date is the last day of a month, this functor will attempt
  43. * to adjust to the end of the month.
  44. */
  45. template<class date_type>
  46. class month_functor
  47. {
  48. public:
  49. typedef typename date_type::duration_type duration_type;
  50. typedef typename date_type::calendar_type cal_type;
  51. typedef typename cal_type::ymd_type ymd_type;
  52. typedef typename cal_type::day_type day_type;
  53. month_functor(int f) : f_(f), origDayOfMonth_(0) {}
  54. duration_type get_offset(const date_type& d) const
  55. {
  56. ymd_type ymd(d.year_month_day());
  57. if (origDayOfMonth_ == 0) {
  58. origDayOfMonth_ = ymd.day;
  59. day_type endOfMonthDay(cal_type::end_of_month_day(ymd.year,ymd.month));
  60. if (endOfMonthDay == ymd.day) {
  61. origDayOfMonth_ = -1; //force the value to the end of month
  62. }
  63. }
  64. typedef date_time::wrapping_int2<short,1,12> wrap_int2;
  65. typedef typename wrap_int2::int_type int_type;
  66. wrap_int2 wi(ymd.month);
  67. //calc the year wrap around, add() returns 0 or 1 if wrapped
  68. int_type year = wi.add(static_cast<int_type>(f_));
  69. year = static_cast<int_type>(year + ymd.year); //calculate resulting year
  70. // std::cout << "trace wi: " << wi.as_int() << std::endl;
  71. // std::cout << "trace year: " << year << std::endl;
  72. //find the last day for the new month
  73. day_type resultingEndOfMonthDay(cal_type::end_of_month_day(year, wi.as_int()));
  74. //original was the end of month -- force to last day of month
  75. if (origDayOfMonth_ == -1) {
  76. return date_type(year, wi.as_int(), resultingEndOfMonthDay) - d;
  77. }
  78. day_type dayOfMonth = origDayOfMonth_;
  79. if (dayOfMonth > resultingEndOfMonthDay) {
  80. dayOfMonth = resultingEndOfMonthDay;
  81. }
  82. return date_type(year, wi.as_int(), dayOfMonth) - d;
  83. }
  84. //! Returns a negative duration_type
  85. duration_type get_neg_offset(const date_type& d) const
  86. {
  87. ymd_type ymd(d.year_month_day());
  88. if (origDayOfMonth_ == 0) {
  89. origDayOfMonth_ = ymd.day;
  90. day_type endOfMonthDay(cal_type::end_of_month_day(ymd.year,ymd.month));
  91. if (endOfMonthDay == ymd.day) {
  92. origDayOfMonth_ = -1; //force the value to the end of month
  93. }
  94. }
  95. typedef date_time::wrapping_int2<short,1,12> wrap_int2;
  96. typedef typename wrap_int2::int_type int_type;
  97. wrap_int2 wi(ymd.month);
  98. //calc the year wrap around, add() returns 0 or 1 if wrapped
  99. int_type year = wi.subtract(static_cast<int_type>(f_));
  100. year = static_cast<int_type>(year + ymd.year); //calculate resulting year
  101. //find the last day for the new month
  102. day_type resultingEndOfMonthDay(cal_type::end_of_month_day(year, wi.as_int()));
  103. //original was the end of month -- force to last day of month
  104. if (origDayOfMonth_ == -1) {
  105. return date_type(year, wi.as_int(), resultingEndOfMonthDay) - d;
  106. }
  107. day_type dayOfMonth = origDayOfMonth_;
  108. if (dayOfMonth > resultingEndOfMonthDay) {
  109. dayOfMonth = resultingEndOfMonthDay;
  110. }
  111. return date_type(year, wi.as_int(), dayOfMonth) - d;
  112. }
  113. private:
  114. int f_;
  115. mutable short origDayOfMonth_;
  116. };
  117. //! Functor to iterate a over weeks
  118. template<class date_type>
  119. class week_functor
  120. {
  121. public:
  122. typedef typename date_type::duration_type duration_type;
  123. typedef typename date_type::calendar_type calendar_type;
  124. week_functor(int f) : f_(f) {}
  125. duration_type get_offset(const date_type& d) const
  126. {
  127. // why is 'd' a parameter???
  128. // fix compiler warnings
  129. d.year();
  130. return duration_type(f_*calendar_type::days_in_week());
  131. }
  132. duration_type get_neg_offset(const date_type& d) const
  133. {
  134. // fix compiler warnings
  135. d.year();
  136. return duration_type(-f_*calendar_type::days_in_week());
  137. }
  138. private:
  139. int f_;
  140. };
  141. //! Functor to iterate by a year adjusting for leap years
  142. template<class date_type>
  143. class year_functor
  144. {
  145. public:
  146. //typedef typename date_type::year_type year_type;
  147. typedef typename date_type::duration_type duration_type;
  148. year_functor(int f) : _mf(f * 12) {}
  149. duration_type get_offset(const date_type& d) const
  150. {
  151. return _mf.get_offset(d);
  152. }
  153. duration_type get_neg_offset(const date_type& d) const
  154. {
  155. return _mf.get_neg_offset(d);
  156. }
  157. private:
  158. month_functor<date_type> _mf;
  159. };
  160. } }//namespace date_time
  161. #endif