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