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
15namespace boost {
16namespace 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;
25 day_functor(int f) : f_(f) {}
26 duration_type get_offset(const date_type&) const
27 {
28 return duration_type(f_);
29 }
30 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
57 month_functor(int f) : f_(f), origDayOfMonth_(0) {}
58 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(v: 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
87 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(v: 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;
126 week_functor(int f) : f_(f) {}
127 duration_type get_offset(const date_type&) const
128 {
129 return duration_type(f_*static_cast<int>(calendar_type::days_in_week()));
130 }
131 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;
146 year_functor(int f) : _mf(f * 12) {}
147 duration_type get_offset(const date_type& d) const
148 {
149 return _mf.get_offset(d);
150 }
151 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

source code of include/boost/date_time/adjust_functors.hpp