public ScheduledEventCollection Clone() { ScheduledEventCollection newCol = new ScheduledEventCollection(); for (int i = 0; i < this.Count; i++) { newCol.Add((ScheduledEvent)this[i].Clone(), this.GetKey(i)); } return(newCol); }
/// <summary> /// Creates a list array of ScheduledEvent objects and sorts them by the times they should execute. /// </summary> /// <param name="textOut">An array of ScheduleEventParams objects used to build the ScheduledEvent objects from.</param> public ScheduleManager(ScheduledEventParamsCollection schedParams) { ScheduledEventCollection unsorted = new ScheduledEventCollection(); for (int i = 0; i < schedParams.Count; i++) { // We'll set this to true if all the stats match. bool validEvent = false; // Make sure we're between the Start and End dates before we start parsing anything. if ((DateTime.Now > schedParams[i].StartDate) && (schedParams[i].EndDate.Ticks == 0 || schedParams[i].EndDate > DateTime.Now)) { switch (schedParams[i].EventFreq) { case EventFrequency.daily: if (schedParams[i].EventInterval == 1) { // This event occurs every day, so we'll set it to valid validEvent = true; } else { // Here's were we need to figure out if the current day is an // even divisor of EventInterval field, based on the StartDate // of the event. // First thing we do is create a DateTime object equal to the // StartDate of the event. DateTime dt = schedParams[i].StartDate; // We're ignoring the year in this equation, so if the StartDate's // DayOfYear value is greater than today's DayOfYear value, we need // to advance our DateTime object to Jan 1st. if (dt.DayOfYear > DateTime.Now.DayOfYear) { dt.AddDays(Convert.ToDouble(schedParams[i].EventInterval)); } // Now, we slide the StartDate object forward in time, by the value // of the 'EventInterval' field until it is either greater than // or equal to today's 'DayOfYear' value. while (dt.DayOfYear < DateTime.Now.DayOfYear) { dt.AddDays(Convert.ToDouble(schedParams[i].EventInterval)); } // If the two DateTime object's ended up with matching 'DayOfYear' // values, then we have a winner. if (dt.DayOfYear == DateTime.Now.DayOfYear) { validEvent = true; } } break; case EventFrequency.weekly: if (schedParams[i].EventInterval == 1) { // Event fires every week, so we just have to determine if this // is one of the event's specified days. if (schedParams[i].DaysOfWeek.ToLower().IndexOf(DateTime.Now.ToString("dddd").ToLower()) > -1) { // We found 'today' in the DaysOfWeek list, so add the event. validEvent = true; } } else { // Again, we have to calculate if we've moved forward in time the // proper number of weeks before firing. DateTime dt = schedParams[i].StartDate; int sWeekOfYear = (int)Math.Round(Convert.ToDouble(dt.DayOfYear / 7), MidpointRounding.AwayFromZero); int nWeekOfYear = (int)Math.Round(Convert.ToDouble(DateTime.Now.DayOfYear / 7), MidpointRounding.AwayFromZero); // If the start week is higher, we've got to 'slide' foward in time till we come // back around to the first of the year. if (sWeekOfYear > nWeekOfYear) { while (sWeekOfYear <= 52) { sWeekOfYear += schedParams[i].EventInterval; } sWeekOfYear -= 52; } // Now, we slide the StartDate week forward in time, until it is greater // than or equal to the value of the current week. while (sWeekOfYear < nWeekOfYear) { sWeekOfYear += schedParams[i].EventInterval; } // If the two are equal, then we have a winner. if (sWeekOfYear == nWeekOfYear) { validEvent = true; } } break; case EventFrequency.monthly: if (schedParams[i].MonthsOfYear.ToLower().IndexOf(Convert.ToString((MonthOfYear)DateTime.Now.Month).ToLower()) > -1) { // Valid month for this event. Keep parsing. if (schedParams[i].DayOfMonth > 0) { // This event only fires on a specific day. if (DateTime.Now.Day == schedParams[i].DayOfMonth) { validEvent = true; } } else { // This event fires every X occurance of a specific day of the week. if (DateTime.Now.DayOfWeek.ToString().ToLower() == schedParams[i].DaysOfWeek.ToLower()) { // Right day, now we just have to figure out if it's the correct // occurance of that day. // TODO :: Add code to do above here. } } } break; } } // If we've got a valid event schedule, we need to create the event(s). if (validEvent) { if (schedParams[i].RepeatInterval.TotalSeconds > 0) { // Setup a repeating event. // Start with the event's scheduled time to fire. DateTime evtTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, schedParams[i].TimeOfDay.Hours, schedParams[i].TimeOfDay.Minutes, schedParams[i].TimeOfDay.Seconds); // Then we determine the time at which the event stops repeating. DateTime evtStop; if (schedParams[i].UntilDuration != null && schedParams[i].UntilDuration.TotalSeconds > 0) { evtStop = evtTime.Add(schedParams[i].UntilDuration); } else if (schedParams[i].UntilTimeOfDay.TotalSeconds > 0) { evtStop = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, schedParams[i].UntilTimeOfDay.Hours, schedParams[i].UntilTimeOfDay.Minutes, 00); } else { evtStop = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 23, 59, 59); } // Now we start adding events until the evtTime value exceeds the evtStop value; while (evtTime.Ticks <= evtStop.Ticks) { string evtName; if (schedParams[i].ParentParams != null) { evtName = schedParams[i].ParentParams.RollupName; } else { evtName = schedParams[i].TimeOfDay.ToString().Substring(0, 8); } unsorted.Add(new ScheduledEvent(i, evtName, evtTime.TimeOfDay)); #region Debug Output #if VERBOSE Console.WriteLine("New Event @: {0}", evtTime); #endif #endregion evtTime = evtTime.Add(schedParams[i].RepeatInterval); } } else { // This is a just a single event. string evtName; if (schedParams[i].ParentParams != null) { evtName = schedParams[i].ParentParams.RollupName + " [" + schedParams[i].TimeOfDay.ToString().Substring(0, 8) + "]"; } else { evtName = schedParams[i].TimeOfDay.ToString().Substring(0, 8); } unsorted.Add(new ScheduledEvent(i, evtName, schedParams[i].TimeOfDay)); } } } // Once we're all done adding all valid events to the ScheduledEventList object, we // have to 'sort' them into the proper order. We use a simple 'bubble' sort // to accomplish this, since there should never be so many events as to make // this impractical. for (int r = 0; r < unsorted.Count; r++) { for (int t = 0; t < unsorted.Count; t++) { if (unsorted[t].IsAfter(unsorted[r])) { unsorted.Move(t, r); } } } // Then, we Clone the (now) sorted list into our global variable reference events = unsorted.Clone() as ScheduledEventCollection; // After that, we need to find the first event in the list who's scheduled // time has not already passed. GetNextEvent(); #region Debug Output #if VERBOSE foreach (ScheduledEvent evnt in events) { Console.WriteLine("{0}: {1} [{2}]", evnt.EventID, evnt.EventName, evnt.ScheduledTime.ToString().Substring(0, 8)); } #endif #endregion }