2 The software in this package is distributed under the GNU General
3 Public License version 2 (with a special exception described below).
5 A copy of GNU General Public License (GPL) is included in this distribution,
6 in the file COPYING.GPL.
8 As a special exception, if other files instantiate templates or use macros
9 or inline functions from this file, or you compile this file and link it
10 with other works to produce a work based on this file, this file
11 does not by itself cause the resulting work to be covered
12 by the GNU General Public License.
14 However the source code for this file must still be made available
15 in accordance with section (3) of the GNU General Public License.
17 This exception does not invalidate any other reasons why a work based
18 on this file might be covered by the GNU General Public License.
21 * @brief repeating time-points and intervals
23 * @copyright Copyright © 2009 by Intra2net AG
36 const time_t WeekCron::StNimmerleinsDay = static_cast<time_t>(INT_MAX);
39 * Constructor, leaves object in invalid state
51 * @param daystring String representing the active weekdays as numbers. 0 is Sunday.
52 * @param begin Start point of time in seconds since the start of the day
54 WeekCron::WeekCron(const std::string& daystring, const int begin)
64 * @param daystring String representing the active weekdays as numbers. 0 is Sunday.
65 * @param begin Start point of time in seconds since the start of the day
66 * @param end End point of time in seconds since the start of the day. Only used when every != -1
67 * @param every Repeat event every xxx seconds in the half-open interval of begin and end. -1 is disabled
69 WeekCron::WeekCron(const std::string& daystring, const int begin, const int end, const int every)
79 * @param week I2n::Time::Week object representing the active days
80 * @param begin Start point of time in seconds since the start of the day
82 WeekCron::WeekCron(const I2n::Time::Week& week, const int begin)
92 * @param week I2n::Time::Week object representing the active days
93 * @param begin Start point of time in seconds since the start of the day
94 * @param end End point of time in seconds since the start of the day. Only used when every != -1
95 * @param every Repeat event every xxx seconds in the half-open interval of begin and end. -1 is disabled
97 WeekCron::WeekCron(const I2n::Time::Week& week, const int begin, const int end, const int every)
106 * Checks if the input values are sane
107 * @return True if sane, false otherweise
109 bool WeekCron::is_sane() const
111 if (Begin < 0 || Begin > 86399)
116 if (End < 0 || End > 86400 ||
117 Every < 1 || Every > 86400 ||
126 * Returns the next point in time the item is scheduled for.
127 * Handles the full possibilities of WeekCron.
128 * @note if it is scheduled for calc_from we return the next schedule, not now!
129 * @param calc_from unix-time to start calculating from (0 means now)
130 * @return Next point in time the item is scheduled for
131 * returns constant #StNimmerleinsDay if it is scheduled never
133 time_t WeekCron::get_next_run(time_t calc_from) const
136 calc_from=time(NULL);
139 throw std::runtime_error("illegal cron value");
141 if (calc_from <= 86400*14)
142 throw std::runtime_error("WeekCron doesn't work for timestamps near 0");
145 return StNimmerleinsDay;
150 return get_next_point(calc_from,Begin,true);
155 time_t next_begin = get_next_point(calc_from,Begin,true);
156 if (next_begin > get_next_point(calc_from,End-1,true))
158 // next begin > next end means we are at the begin or within the interval
160 time_t interval_begin=get_previousnow_point(calc_from,Begin,true);
162 time_t within_interval=calc_from - interval_begin;
163 time_t since_lastrun=within_interval % Every;
164 time_t next_exec=calc_from+(Every-since_lastrun);
166 // next step at or after end?
167 if (next_exec > get_next_point(calc_from,End-1,true))
168 return get_next_point(calc_from,Begin,true);
174 // next begin < next end means we are out of the interval: next begin is next run
181 * Returns the next point in time the item is scheduled for. Does not care about intervals.
182 * Returns next point if scheduled for @a calc_from.
183 * @param calc_from Point of time to start calculations from
184 * @param daysec Start point of time in seconds since the start of the day
185 * @param todaycheck If true we check if the calculated time point is before
186 our @a calc_from calcucation start point.
187 If yes, we will advance to the next day.
188 * @return Next point in time
190 time_t WeekCron::get_next_point(const time_t calc_from, const int daysec, const bool todaycheck) const
193 if (localtime_r(&calc_from,&ft) == NULL)
196 // take care of the weekday
197 ft.tm_mday+=Week.days_till_set(static_cast<Week::WeekDay>(ft.tm_wday)); //lint !e737 !e713
199 fill_tm_with_wallclock(&ft,daysec);
201 // tm_isdst means to use the dst in use at the given time
204 time_t target=mktime(&ft);
206 // check for completely illegal time, should not happen without bug in this func,
207 // return calc_from as safeguard
208 if (target == (time_t)-1)
211 // todays schedule could already been through or now
212 if (todaycheck && target <= calc_from)
214 // not today but the next matching weekday
217 target=get_next_point(mktime(&ft),daysec,false);
224 * Returns the previous or current point in time the item was scheduled for.
225 * Does not care about intervals.
226 * Returns @a calc_from if scheduled for @a calc_from.
227 * @param calc_from Point of time to start calculations from
228 * @param daysec Start point of time in seconds since the start of the day
229 * @param todaycheck If true we check if the calculated time point is after
230 our @a calc_from calcucation start point.
231 If yes, we will go back to the previos day
232 * @return Previous point in time
234 time_t WeekCron::get_previousnow_point(const time_t calc_from, const int daysec, const bool todaycheck) const
237 if (localtime_r(&calc_from,&ft) == NULL)
240 // take care of the weekday
241 ft.tm_mday-=Week.days_since_set(static_cast<Week::WeekDay>(ft.tm_wday)); //lint !e737 !e713
243 fill_tm_with_wallclock(&ft,daysec);
245 // tm_isdst means to use the dst in use at the given time
248 time_t target=mktime(&ft);
250 // check for completely illegal time, should not happen without bug in this func,
251 // return calc_from as safeguard
252 if (target == (time_t)-1)
255 // target later than we are looking for
256 // target==calc_from is ok (that's why it is called lastnow...)
257 if (todaycheck && target > calc_from)
259 // not today but the previous matching weekday
262 target=get_previousnow_point(mktime(&ft),daysec,false);
269 * Converts @a daysec into hour/minute/second and fills it into the provided struct tm
270 * @param ft struct tm to fill wallclock time into
271 * @param daysec Start point of time in seconds since the start of the day
273 void WeekCron::fill_tm_with_wallclock(struct tm *ft, const int daysec) const
277 ft->tm_hour=remain/3600;
278 remain-=ft->tm_hour*3600;
280 ft->tm_min=remain/60;
281 remain-=ft->tm_min*60;