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