adjust_functors.hpp 5.3 KB

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