public static ScheduleRepeater ParseCronString(string cronString) { ScheduleRepeater s = new ScheduleRepeater(); string[] cronParts = cronString.Split(')'); string timeStrings = cronParts[0].TrimStart(new char[] { '(' }); string[] timeSetStrings = timeStrings.Split(','); s.Times = new List <Dictionary <string, int> >(); foreach (string t in timeSetStrings) { string tx = t.Trim(new char[] { '[', ']' }); string[] timeParts = tx.Split(' '); Dictionary <string, int> time = new Dictionary <string, int>(); time.Add("hours", Convert.ToInt32(timeParts[1])); time.Add("minutes", Convert.ToInt32(timeParts[0])); s.Times.Add(time); } s.Times.Sort(Schedule.CompareTimes); string cronSchedule = cronParts[1].Trim(); string[] scheduleParts = cronSchedule.Split(' '); string[] daysOfMonth = scheduleParts[0].Split(','); s.DaysOfMonth = new List <int>(); for (int i = 0; i < daysOfMonth.Length; i++) { int num; if (Int32.TryParse(daysOfMonth[i], out num)) { s.DaysOfMonth.Add(num); } } s.DaysOfMonth.Sort(); string[] monthsOfYear = scheduleParts[1].Split(','); s.MonthsOfYear = new List <int>(); for (int i = 0; i < monthsOfYear.Length; i++) { int num; if (Int32.TryParse(monthsOfYear[i], out num)) { s.MonthsOfYear.Add(num); } } s.MonthsOfYear.Sort(); string[] daysOfWeek = scheduleParts[2].Split(','); s.DaysOfWeek = new List <int>(); for (int i = 0; i < daysOfWeek.Length; i++) { int num; if (Int32.TryParse(daysOfWeek[i], out num)) { s.DaysOfWeek.Add(num); } } s.DaysOfWeek.Sort(); int x; if (Int32.TryParse(scheduleParts[3], out x)) { s.SkipWeeks = x; } if (Int32.TryParse(scheduleParts[4], out x)) { s.SkipMonths = x; } return(s); }
public static ScheduleRepeater ParseCronString(string cronString) { ScheduleRepeater s = new ScheduleRepeater(); string[] cronParts = cronString.Split(')'); string timeStrings = cronParts[0].TrimStart(new char[] { '(' }); string[] timeSetStrings = timeStrings.Split(','); s.Times = new List<Dictionary<string, int>>(); foreach (string t in timeSetStrings) { string tx = t.Trim(new char[] { '[', ']' }); string[] timeParts = tx.Split(' '); Dictionary<string, int> time = new Dictionary<string, int>(); time.Add("hours", Convert.ToInt32(timeParts[1])); time.Add("minutes", Convert.ToInt32(timeParts[0])); s.Times.Add(time); } s.Times.Sort(Schedule.CompareTimes); string cronSchedule = cronParts[1].Trim(); string[] scheduleParts = cronSchedule.Split(' '); string[] daysOfMonth = scheduleParts[0].Split(','); s.DaysOfMonth = new List<int>(); for (int i = 0; i < daysOfMonth.Length; i++) { int num; if (Int32.TryParse(daysOfMonth[i], out num)) { s.DaysOfMonth.Add(num); } } s.DaysOfMonth.Sort(); string[] monthsOfYear = scheduleParts[1].Split(','); s.MonthsOfYear = new List<int>(); for (int i = 0; i < monthsOfYear.Length; i++) { int num; if (Int32.TryParse(monthsOfYear[i], out num)) { s.MonthsOfYear.Add(num); } } s.MonthsOfYear.Sort(); string[] daysOfWeek = scheduleParts[2].Split(','); s.DaysOfWeek = new List<int>(); for (int i = 0; i < daysOfWeek.Length; i++) { int num; if (Int32.TryParse(daysOfWeek[i], out num)) { s.DaysOfWeek.Add(num); } } s.DaysOfWeek.Sort(); int x; if (Int32.TryParse(scheduleParts[3], out x)) { s.SkipWeeks = x; } if (Int32.TryParse(scheduleParts[4], out x)) { s.SkipMonths = x; } return s; }
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."); }