public DateTime GetNextScheduled() { ScheduleRepeater r = Schedule.ParseCronString(this.RepeatSchedule); DateTime current = this.NextScheduledDate; // if there's more than one time, and if there's a time that's later than the // current, let's use the same day and return later time foreach (Dictionary <string, int> t in r.Times) { // since we've sorted in order we loop through and return earliest time that's later than current if (t["hours"] > current.Hour || (t["hours"] == current.Hour && t["minutes"] > current.Minute)) { return(new DateTime(current.Year, current.Month, current.Day, t["hours"], t["minutes"], 0)); } } // if there's no other times that're later than current, we continue and set the next date // if there are specific dates set, we'll use the next date // for each of the following, we'll use r.Times[0] as it'll be the first time that day, in case // there are more than one time set to run // to start we check to see if this is set up to skip months if (r.SkipMonths != 0) { DateTime newDate = current.AddMonths(r.SkipMonths + 1); return(new DateTime(newDate.Year, newDate.Month, newDate.Day, r.Times[0]["hours"], r.Times[0]["minutes"], 0)); } //next we try checking for specific days of the month if (r.DaysOfMonth.Count > 0) { DateTime newDate; if (r.DaysOfMonth.Count == 1) // if there's only one day of the month, we just add a month { newDate = current.AddMonths(1); // addmonths automatically adjusts the day of the month back if // it would overflow the month return(new DateTime(newDate.Year, newDate.Month, newDate.Day, r.Times[0]["hours"], r.Times[0]["minutes"], 0)); } // calculate number of days to add int addDays = 0; int daysThisMonth = DateTime.DaysInMonth(current.Year, current.Month); DateTime nextMonth = current.AddMonths(1); int daysNextMonth = DateTime.DaysInMonth(nextMonth.Year, nextMonth.Month); foreach (int date in r.DaysOfMonth) { // here we're checking for a later date this same month if (date > current.Day) { if (date > daysThisMonth) { // if it's set to run on a date that's greater than the number of days in the month, // we're going to default back to the last day of the month addDays = daysThisMonth - current.Day; } else { addDays = date - current.Day; } break; } } if (addDays == 0) { // if addDays is still 0, then whatever date we're on is the last shcduled for this month, and we // need to move on to next month if (r.DaysOfMonth[0] > daysNextMonth) { return(new DateTime(nextMonth.Year, nextMonth.Month, daysNextMonth, r.Times[0]["hours"], r.Times[0]["minutes"], 0)); } else { addDays = daysThisMonth - current.Day + r.DaysOfMonth[0]; } } if (addDays == 0) { // if we're still running zero there may be a corner case where the process is repeating // the last couple days every month and we're currently in a month that's shorter than the // schedule. So we'll just return next month return(new DateTime(nextMonth.Year, nextMonth.Month, daysNextMonth, r.Times[0]["hours"], r.Times[0]["minutes"], 0)); } newDate = current.AddDays(addDays); return(new DateTime(newDate.Year, newDate.Month, newDate.Day, r.Times[0]["hours"], r.Times[0]["minutes"], 0)); } // if skipweeks is set we'll set a date that number of weeks ahead. if (r.SkipWeeks != 0) { DateTime newDate = current.AddDays(7 * (r.SkipWeeks + 1)); return(new DateTime(newDate.Year, newDate.Month, newDate.Day, r.Times[0]["hours"], r.Times[0]["minutes"], 0)); } // if we're going by days of the week, we'll set to run on the next available day which matches. if (r.DaysOfWeek.Count > 0) { int addDays = 0; foreach (int day in r.DaysOfWeek) { if (day > Convert.ToInt32(current.DayOfWeek)) { // if there's a day later in the week addDays = day - Convert.ToInt32(current.DayOfWeek); break; } } if (addDays == 0) { // we couldn't find a later day this week, so we'll go to next week addDays = 7 - Convert.ToInt32(current.DayOfWeek) + r.DaysOfWeek[0]; } // set new date based on adding number of days DateTime newDate = current.AddDays(addDays); // return datetime with earliest runtime that day return(new DateTime(newDate.Year, newDate.Month, newDate.Day, r.Times[0]["hours"], r.Times[0]["minutes"], 0)); } throw new Exception("Cannot find next scheduled date. Parsing cronstring values yeilded no available dates."); }