///|
pub fn CronExpr::matches(self : CronExpr, time : Time) -> Bool {
let min_match = self.minute.matches(time.minute)
let hour_match = self.hour.matches(time.hour)
let month_match = self.month.matches(time.month)
let dom_restricted = match self.day_of_month {
All => false
_ => true
}
let dow_restricted = match self.day_of_week {
All => false
_ => true
}
let day_match = if dom_restricted && dow_restricted {
self.day_of_month.matches(time.day) ||
self.day_of_week.matches(time.weekday)
} else {
self.day_of_month.matches(time.day) &&
self.day_of_week.matches(time.weekday)
}
min_match && hour_match && month_match && day_match
}
///|
fn CronField::matches(self : CronField, value : Int) -> Bool {
match self {
All => true
Value(n) => n == value
Range(start, end) => value >= start && value <= end
Step(base, step) =>
match base {
All => value % step == 0
Range(start, end) =>
value >= start && value <= end && (value - start) % step == 0
Value(n) => n == value
Step(_, _) => false
List(_) => false
}
List(arr) => {
for i = 0; i < arr.length(); i = i + 1 {
if arr[i].matches(value) {
return true
}
}
false
}
}
}
///|
pub fn CronExpr::next(self : CronExpr, from : Time) -> Result[Time, String] {
let mut current = add_minute(from)
let mut iterations = 0
while iterations < 100000 {
iterations = iterations + 1
if !self.month.matches(current.month) {
current.month = current.month + 1
if current.month > 12 {
current.month = 1
current.year = current.year + 1
}
current.day = 1
current.hour = 0
current.minute = 0
current.weekday = weekday(current.year, current.month, current.day)
continue
}
let dom_restricted = match self.day_of_month {
All => false
_ => true
}
let dow_restricted = match self.day_of_week {
All => false
_ => true
}
let day_match = if dom_restricted && dow_restricted {
self.day_of_month.matches(current.day) ||
self.day_of_week.matches(current.weekday)
} else {
self.day_of_month.matches(current.day) &&
self.day_of_week.matches(current.weekday)
}
if !day_match {
current.day = current.day + 1
if current.day > days_in_month(current.year, current.month) {
current.day = 1
current.month = current.month + 1
if current.month > 12 {
current.month = 1
current.year = current.year + 1
}
}
current.hour = 0
current.minute = 0
current.weekday = weekday(current.year, current.month, current.day)
continue
}
if !self.hour.matches(current.hour) {
current.hour = current.hour + 1
if current.hour > 23 {
current.hour = 0
current.day = current.day + 1
if current.day > days_in_month(current.year, current.month) {
current.day = 1
current.month = current.month + 1
if current.month > 12 {
current.month = 1
current.year = current.year + 1
}
}
current.weekday = weekday(current.year, current.month, current.day)
}
current.minute = 0
continue
}
if !self.minute.matches(current.minute) {
current = add_minute(current)
continue
}
return Ok(current)
}
Err("Cannot find next execution time (unreachable or too far in the future)")
}