Ejemplo n.º 1
0
        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;
        }
Ejemplo n.º 2
0
        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;
        }
Ejemplo n.º 3
0
        // 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;
        }
Ejemplo n.º 4
0
        // 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;
        }
Ejemplo n.º 5
0
        // 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;
        }
Ejemplo n.º 6
0
        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;
        }
Ejemplo n.º 7
0
 /// <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;
 }
Ejemplo n.º 8
0
 /// <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;
 }
Ejemplo n.º 9
0
        // 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;
        }