public IEnumerable <TimedEvent> GetRange(DateTime RangeStart, DateTime RangeEnd) { TimedEvent RangeEvent = new TimedEvent(RangeStart, RangeEnd); IEnumerable <TimedEvent> Enum1 = _OffsetTime.Ticks >= 0 ? _Schedule.GetRange(SafeDateTimeAdd(RangeStart, _OffsetTime.Negate()), DateTime.MaxValue) : _Schedule.GetRange(SafeDateTimeAdd(RangeStart, _OffsetTime), DateTime.MaxValue); foreach (TimedEvent Evt in Enum1) { TimedEvent OffsetEvt; try { OffsetEvt = new TimedEvent(Evt.StartTime + _OffsetTime, Evt.EndTime + _OffsetTime); } catch (ArgumentOutOfRangeException) { // This occurs when _OffsetTime is added to StartTime or EndTime and causes an overflow or underflow. // In this case, we ignore this event, since it can't be represented. continue; } if (OffsetEvt.StartTime >= RangeEnd) { break; } if (OffsetEvt.Intersects(RangeEvent)) { yield return(OffsetEvt); } } yield break; }
public IEnumerable <TimedEvent> GetRange(DateTime RangeStart, DateTime RangeEnd) { // Handle zero interval condition if (_Interval == TimeSpan.Zero) { yield break; } // Check event intersection with range TimeSpan RangeDuration = RangeEnd - RangeStart; DateTime IterateStart = SynchronizeTime(RangeStart); DateTime IterateEnd = RangeEnd; // Check first event // EEEE EEEE // WWWWWWW TimedEvent FirstEvt = new TimedEvent( (IterateStart.Ticks >= _Interval.Ticks ? // Handle when IterateStart is near DateTime.MinValue IterateStart.Subtract(_Interval) : DateTime.MinValue), _Duration); if (FirstEvt.StartTime != IterateStart && FirstEvt.Intersects(new TimedEvent(RangeStart, RangeEnd))) { yield return(FirstEvt); } if (DateTime.MaxValue - IterateEnd >= _Interval) { for (DateTime dt = IterateStart; dt < IterateEnd; dt = dt.Add(_Interval)) { yield return(new TimedEvent(dt, dt.Add(_Duration))); } } else { // Special case when end of iteration is very close to DateTime.MaxValue // IterateEnd must be at least > Interval time to match any events if (IterateEnd.Ticks >= _Interval.Ticks) { DateTime IterateEnd2 = IterateEnd.Subtract(_Interval); for (DateTime dt = IterateStart; ; dt = dt.Add(_Interval)) { yield return(new TimedEvent(dt, dt.Add(_Duration))); if (dt >= IterateEnd2) { break; } } } } yield break; }
// Optimized 2008-07-13 public IEnumerable <TimedEvent> GetRange(DateTime RangeStart, DateTime RangeEnd) { // AAAA // BBBB // xxxxxx // // AA // BB // xxxx // // AAAA // BBBB // xxxxxx // CC // xxxxxxxx TimedEvent MatchEvent = null; foreach (TimedEvent A in _Schedule.GetRange(RangeStart, RangeEnd)) { if (MatchEvent == null) { // Load up MatchEvent MatchEvent = A; } else if (MatchEvent.Intersects(A) || MatchEvent.IsAdjacentTo(A)) { // Compute union and move on MatchEvent = MatchEvent.Union(A)[0]; } else { // No intersection, return MatchEvent yield return(MatchEvent); MatchEvent = A; } } // If MatchEvent has a value, return it if (MatchEvent != null) { yield return(MatchEvent); } yield break; }
// Optimized 2008-07-13 public IEnumerable <TimedEvent> GetRange(DateTime RangeStart, DateTime RangeEnd) { /* * Input: * A: xxxx xxxx * B: xxxxxx * * Compare: * A: AAAA xxxx * B: BBBBBB * * Compute difference: * * A: AA-- xxxx * B: --BBBB * * Compare next: * A: AA xxxx * B: BBBB * * Compare next: * A: AA BBBB * B: xxxx * * Compare next: * A: RR BBBB * B: AAAA * * Compute difference: * A: RR --BB * B: AA-- * * Result: * RR RR RR * */ IEnumerator <TimedEvent> ListIterator = _Schedule.GetRange(RangeStart, RangeEnd).GetEnumerator(); if (ListIterator.MoveNext()) { TimedEvent DiffEvent = null; DateTime Max = ListIterator.Current.StartTime; var BufferList = new List <TimedEvent>(new TimedEvent[] { ListIterator.Current }); do { // Get next event TimedEvent A = BufferList[0]; BufferList.RemoveAt(0); // Figure out what to do with it if (DiffEvent == null) { DiffEvent = A; } else if (DiffEvent.Intersects(A)) { // With an intersection, add difference events to list and redo TimedEvent[] DiffEvents = DiffEvent.Difference(A); if (DiffEvents.Length > 0) { TimedEvent LastEvent = DiffEvents[DiffEvents.Length - 1]; if (LastEvent.StartTime > Max) { Max = LastEvent.StartTime; } BufferList.AddRange(DiffEvents); BufferList.Sort(); } DiffEvent = null; } else { // No intersection, return working DiffEvent yield return(DiffEvent); DiffEvent = A; } // Fetch more events? if (BufferList.Count == 0) { while (ListIterator.MoveNext()) { TimedEvent Event1 = ListIterator.Current; BufferList.Add(Event1); // Stop buffering when we pass the maximum StartTime we need if (Event1.StartTime > Max) { Max = Event1.StartTime; break; } } } // Continue as long as more data exists } while (BufferList.Count > 0); // If working DiffEvent has a value, return it if (DiffEvent != null) { yield return(DiffEvent); } } yield break; }
// Optimized 2008-07-13 public IEnumerable <TimedEvent> GetRange(DateTime RangeStart, DateTime RangeEnd) { /* Subtraction complex example: * Input: * A: xxxx xxxx * B: xxxxxx * * Compare: * A: AAAA xxxx * B: BBBBBB * * Compute subtraction: * A: AA-- xxxx * A: --BBBB * * Compare next: * A: RR AAAA * B: BBBB * * Compute subtraction: * A: RR --AA * B: BB-- * * Result: * RR RR * */ // Prepare iterator A. var IteratorA = _ScheduleA.GetRange(RangeStart, RangeEnd).GetEnumerator(); bool HasMoreA = IteratorA.MoveNext(); // If no events in schedule A, quit now. if (!HasMoreA) { yield break; } // Prepare iterator B. var IteratorB = _ScheduleB.GetRange(RangeStart, RangeEnd).GetEnumerator(); bool HasMoreB = IteratorB.MoveNext(); List <TimedEvent> QueueA = new List <TimedEvent>(); bool readvanceFlag; do { readvanceFlag = false; // Get next event for A from queue or iterator, whichever is earliest. TimedEvent A = default(TimedEvent); if (QueueA.Count > 0 && (!HasMoreA || QueueA[0] <= IteratorA.Current)) { // Pop event off queue A. A = QueueA[0]; QueueA.RemoveAt(0); } else if (HasMoreA) { // If queue is empty or iterator's current value is earlier, // get next event from A and put it on the queue. QueueA.Add(IteratorA.Current); HasMoreA = IteratorA.MoveNext(); readvanceFlag = true; continue; } bool recompareFlag; do // comparison code block. { recompareFlag = false; if (!HasMoreB) { // If no more events from B, return remaining events from A. yield return(A); } else { // Compare A <=> B. var B = IteratorB.Current; // AAAA // BBBB if (A.EndTime <= B.StartTime) { // No intersection, return A. yield return(A); } // AAAA or AAAA or AAAA or AA // BBBB BB BBBB BBBB else if (B.EndTime > A.StartTime) { // AAAA or AAAA // BBBB BB if (A.StartTime < B.StartTime) { var NewA = new TimedEvent(A.StartTime, B.StartTime); QueueA.Add(NewA); if (B.EndTime < A.EndTime) { var NewA2 = new TimedEvent(B.EndTime, A.EndTime); QueueA.Add(NewA2); } } // AAAA or AA // BBBB BBBB else if (B.EndTime < A.EndTime) { var NewA = new TimedEvent(B.EndTime, A.EndTime); QueueA.Add(NewA); } } else { // AAAA // BBBB // No intersection, advance schedule B and recompare. HasMoreB = IteratorB.MoveNext(); recompareFlag = true; continue; } } // if (!HasMoreB) else } while (recompareFlag); // Continue until no more events from A. } while (readvanceFlag || HasMoreA || QueueA.Count > 0); yield break; }
public IEnumerable <TimedEvent> GetRange(DateTime RangeStart, DateTime RangeEnd) { // Determine start of iteration by stepping back _Duration time, then adding 1 minute (smallest increment in cron) TimeSpan OneMinute = new TimeSpan(0, 1, 0); TimeSpan StepBackTime = _Duration >= OneMinute?_Duration.Subtract(OneMinute) : TimeSpan.Zero; DateTime IterateStart = RangeStart.Ticks >= StepBackTime.Ticks ? RangeStart.Subtract(StepBackTime) : DateTime.MinValue; // Strip seconds, ms, and ticks IterateStart.AddTicks(-(IterateStart.Ticks % TimeSpan.TicksPerMinute)); // Start iteration with restricted ranges int?MonthStart = IterateStart.Month; int?DayStart = IterateStart.Day; int?HourStart = IterateStart.Hour; int?MinuteStart = IterateStart.Minute; for (int Year = IterateStart.Year; Year <= RangeEnd.Year; Year++) { var Months = _MonthLookup.PickList .Where(x => MonthStart.HasValue ? x >= MonthStart.Value : true); foreach (int Month in Months) { var DOWCounter = new int[] { 0, 0, 0, 0, 0, 0, 0 }; var MonthDays = Calendar.GetMonthDays(Year, Month); var Days = _DayLookup.PickList .Select(x => x < 0 ? MonthDays + x + 1 : x) .Where(x => (DayStart.HasValue ? x >= DayStart.Value : true) && x <= MonthDays); if (MonthStart.HasValue && Month != MonthStart.Value) { MonthStart = DayStart = HourStart = MinuteStart = null; } foreach (int DayIndex in Days) { // Resolve negative Day as index from last day of the month. int Day = DayIndex < 0 ? MonthDays + DayIndex + 1 : DayIndex; if (DayStart.HasValue && Day != DayStart.Value) { DayStart = HourStart = MinuteStart = null; } // Compute day of week. int DOW = (int)new DateTime(Year, Month, Day).DayOfWeek; // Skip this day if DOW doesn't match if (!_DayOfWeekLookup[DOW]) { continue; } DOWCounter[DOW]++; if (_DayOfWeekLookup.OccurranceIndex.HasValue) { // Check DOW occurance index. // Handle special case for last occurance (negative range). int occuranceIndex = _DayOfWeekLookup.OccurranceIndex < 0 ? // Compute last occurrance index. ComputeLastDOWOccurance(Year, Month, DOW) + _DayOfWeekLookup.OccurranceIndex.Value + 1 : _DayOfWeekLookup.OccurranceIndex.Value - 1; if (occuranceIndex != DOWCounter[DOW] - 1) { continue; } } var Hours = _HourLookup.PickList .Where(x => HourStart.HasValue ? x >= HourStart.Value : true); foreach (int Hour in Hours) { if (HourStart.HasValue && Hour != HourStart.Value) { HourStart = MinuteStart = null; } var Minutes = _MinuteLookup.PickList .Where(x => MinuteStart.HasValue ? x >= MinuteStart.Value : true); foreach (int Minute in Minutes) { DateTime Next = new DateTime(Year, Month, Day, Hour, Minute, 0); if (Next >= RangeEnd) { yield break; } TimedEvent ReturnEvent = new TimedEvent(Next, _Duration); yield return(ReturnEvent); } MinuteStart = null; } HourStart = MinuteStart = null; } DayStart = HourStart = MinuteStart = null; } MonthStart = DayStart = HourStart = MinuteStart = null; } yield break; }
/// <summary> /// Constructor for event with a start and end time. /// </summary> /// <param name="StartTime"></param> /// <param name="EndTime"></param> public OneTimeSchedule(DateTime StartTime, DateTime EndTime) { _Event = new TimedEvent(StartTime, EndTime); _Notation = NotationKind.To; }
/// <summary> /// Constructor for event with a start time and duration. /// </summary> /// <param name="EventTime">Date/time of event.</param> /// <param name="Duration">Duration of event.</param> public OneTimeSchedule(DateTime StartTime, TimeSpan Duration) { _Event = new TimedEvent(StartTime, Duration); _Notation = NotationKind.Lasting; }
// Optimized 2008-07-07 public IEnumerable <TimedEvent> GetRange(DateTime RangeStart, DateTime RangeEnd) { // Get iterators from each schedule List <SpyEnumerator <TimedEvent> > Iterators = new List <SpyEnumerator <TimedEvent> >(_Schedules.Count); foreach (ISchedule Schedule1 in _Schedules) { Iterators.Add(Schedule1.GetRange(RangeStart, RangeEnd).GetSpyEnumerator()); } // Batch loop List <TimedEvent> BatchEvents = new List <TimedEvent>(MaxScheduleBufferSize * _Schedules.Count); for (; ;) { DateTime?BatchEndTime = null; // Peek first events from each iterator foreach (SpyEnumerator <TimedEvent> Iterator in Iterators) { if (Iterator.HasMore) { TimedEvent Evt1 = Iterator.Peek; if (!BatchEndTime.HasValue || Evt1.StartTime < BatchEndTime.Value) { BatchEndTime = Evt1.StartTime; } } } // Check if no more events can be iterated, break out if (!BatchEndTime.HasValue) { break; } // Iterate events up to BatchEndTime foreach (SpyEnumerator <TimedEvent> Iterator in Iterators) { int BatchSize = 0; while (Iterator.HasMore) { TimedEvent Evt1 = Iterator.Peek; if (Evt1.StartTime > BatchEndTime) { break; } Iterator.MoveNext(); BatchEvents.Add(Evt1); BatchSize++; if (BatchSize >= MaxScheduleBufferSize) { // Max buffer size reached // Set new BatchEndTime and skip to next schedule BatchEndTime = Evt1.StartTime; break; } } } // If no more events can be had, break from iteration if (BatchEvents.Count == 0) { break; } // Sort batch results to ensure chronological order, then return each event BatchEvents.Sort(); int BatchIdx; for (BatchIdx = 0; BatchIdx < BatchEvents.Count; BatchIdx++) { TimedEvent Evt1 = BatchEvents[BatchIdx]; if (Evt1.StartTime > BatchEndTime) { break; } yield return(Evt1); } // Clear event list and repeat BatchEvents.RemoveRange(0, BatchIdx); } yield break; }