3 * @brief repeating time-points and intervals
5 * @copyright Copyright © 2009 by Intra2net AG
7 * @contact info@intra2net.com
20 const time_t WeekCron::StNimmerleinsDay = static_cast<time_t>(INT_MAX);
23 * Constructor, leaves object in invalid state
35 * @param daystring String representing the active weekdays as numbers. 0 is Sunday.
36 * @param begin Start point of time in seconds since the start of the day
38 WeekCron::WeekCron(const std::string& daystring, const int begin)
48 * @param daystring String representing the active weekdays as numbers. 0 is Sunday.
49 * @param begin Start point of time in seconds since the start of the day
50 * @param end End point of time in seconds since the start of the day. Only used when every != -1
51 * @param every Repeat event every xxx seconds in the half-open interval of begin and end. -1 is disabled
53 WeekCron::WeekCron(const std::string& daystring, const int begin, const int end, const int every)
63 * @param week I2n::Time::Week object representing the active days
64 * @param begin Start point of time in seconds since the start of the day
66 WeekCron::WeekCron(const I2n::Time::Week& week, const int begin)
76 * @param week I2n::Time::Week object representing the active days
77 * @param begin Start point of time in seconds since the start of the day
78 * @param end End point of time in seconds since the start of the day. Only used when every != -1
79 * @param every Repeat event every xxx seconds in the half-open interval of begin and end. -1 is disabled
81 WeekCron::WeekCron(const I2n::Time::Week& week, const int begin, const int end, const int every)
90 * Checks if the input values are sane
91 * @return True if sane, false otherweise
93 bool WeekCron::is_sane() const
95 if (Begin < 0 || Begin > 86399)
100 if (End < 0 || End > 86400 ||
101 Every < 1 || Every > 86400 ||
110 * Returns the next point in time the item is scheduled for.
111 * Handles the full possibilities of WeekCron.
112 * @note if it is scheduled for calc_from we return the next schedule, not now!
113 * @param calc_from unix-time to start calculating from (0 means now)
114 * @return Next point in time the item is scheduled for
115 * returns constant #StNimmerleinsDay if it is scheduled never
117 time_t WeekCron::get_next_run(time_t calc_from) const
120 calc_from=time(NULL);
123 throw std::runtime_error("illegal cron value");
125 if (calc_from <= 86400*14)
126 throw std::runtime_error("WeekCron doesn't work for timestamps near 0");
129 return StNimmerleinsDay;
134 return get_next_point(calc_from,Begin,true);
139 time_t next_begin = get_next_point(calc_from,Begin,true);
140 if (next_begin > get_next_point(calc_from,End-1,true))
142 // next begin > next end means we are at the begin or within the interval
144 time_t interval_begin=get_previousnow_point(calc_from,Begin,true);
146 time_t within_interval=calc_from - interval_begin;
147 time_t since_lastrun=within_interval % Every;
148 time_t next_exec=calc_from+(Every-since_lastrun);
150 // next step at or after end?
151 if (next_exec > get_next_point(calc_from,End-1,true))
152 return get_next_point(calc_from,Begin,true);
158 // next begin < next end means we are out of the interval: next begin is next run
165 * Returns the next point in time the item is scheduled for. Does not care about intervals.
166 * Returns next point if scheduled for #calc_from.
167 * @param calc_from Point of time to start calculations from
168 * @param daysec Start point of time in seconds since the start of the day
169 * @param todaycheck If true we check if the calculated time point is before
170 our #calc_from calcucation start point.
171 If yes, we will advance to the next day.
172 * @return Next point in time
174 time_t WeekCron::get_next_point(const time_t calc_from, const int daysec, const bool todaycheck) const
177 if (localtime_r(&calc_from,&ft) == NULL)
180 // take care of the weekday
181 ft.tm_mday+=Week.days_till_set(static_cast<Week::WeekDay>(ft.tm_wday)); //lint !e737 !e713
183 fill_tm_with_wallclock(&ft,daysec);
185 // tm_isdst means to use the dst in use at the given time
188 time_t target=mktime(&ft);
190 // check for completely illegal time, should not happen without bug in this func,
191 // return calc_from as safeguard
192 if (target == (time_t)-1)
195 // todays schedule could already been through or now
196 if (todaycheck && target <= calc_from)
198 // not today but the next matching weekday
201 target=get_next_point(mktime(&ft),daysec,false);
208 * Returns the previous or current point in time the item was scheduled for.
209 * Does not care about intervals.
210 * Returns #calc_from if scheduled for #calc_from.
211 * @param calc_from Point of time to start calculations from
212 * @param daysec Start point of time in seconds since the start of the day
213 * @param todaycheck If true we check if the calculated time point is after
214 our #calc_from calcucation start point.
215 If yes, we will go back to the previos day
216 * @return Previous point in time
218 time_t WeekCron::get_previousnow_point(const time_t calc_from, const int daysec, const bool todaycheck) const
221 if (localtime_r(&calc_from,&ft) == NULL)
224 // take care of the weekday
225 ft.tm_mday-=Week.days_since_set(static_cast<Week::WeekDay>(ft.tm_wday)); //lint !e737 !e713
227 fill_tm_with_wallclock(&ft,daysec);
229 // tm_isdst means to use the dst in use at the given time
232 time_t target=mktime(&ft);
234 // check for completely illegal time, should not happen without bug in this func,
235 // return calc_from as safeguard
236 if (target == (time_t)-1)
239 // target later than we are looking for
240 // target==calc_from is ok (that's why it is called lastnow...)
241 if (todaycheck && target > calc_from)
243 // not today but the previous matching weekday
246 target=get_previousnow_point(mktime(&ft),daysec,false);
253 * Converts #daysec into hour/minute/second and fills it into the provided struct tm
254 * @param ft struct tm to fill wallclock time into
255 * @param daysec Start point of time in seconds since the start of the day
257 void WeekCron::fill_tm_with_wallclock(struct tm *ft, const int daysec) const
261 ft->tm_hour=remain/3600;
262 remain-=ft->tm_hour*3600;
264 ft->tm_min=remain/60;
265 remain-=ft->tm_min*60;