Esempio n. 1
0
        }         // Difference

        // ----------------------------------------------------------------------
        public TimeSpan Difference(DateTime date1, DateTime date2)
        {
            if (date1.Equals(date2))
            {
                return(TimeSpan.Zero);
            }
            if (collectorFilter.WeekDays.Count == 0 && collectorFilter.CollectingHours.Count == 0 && collectorFilter.CollectingDayHours.Count == 0)
            {
                return(new DateDiff(date1, date2, calendar.Culture.Calendar, calendar.FirstDayOfWeek, calendar.YearBaseMonth).Difference);
            }

            TimeRange differenceRange = new TimeRange(date1, date2);

            CalendarPeriodCollector collector = new CalendarPeriodCollector(
                collectorFilter, new TimeRange(differenceRange.Start.Date, differenceRange.End.Date.AddDays(1)), SeekDirection.Forward, calendar);

            collector.CollectHours();

            // calculate gaps
            TimeGapCalculator <TimeRange> gapCalculator = new TimeGapCalculator <TimeRange>(calendar);
            ITimePeriodCollection         gaps          = gapCalculator.GetGaps(collector.Periods, differenceRange);

            // calculate difference (sum gap durations)
            TimeSpan difference = gaps.GetTotalDuration(durationProvider);

            return(date1 < date2 ? difference : difference.Negate());
        }         // Difference
Esempio n. 2
0
        }         // FindNextWeek

        // ----------------------------------------------------------------------
        private Week FindPreviousWeek(Week current)
        {
            if (ExcludePeriods.Count == 0)
            {
                return(current.GetPreviousWeek());
            }

            TimeRange limits = new TimeRange(DateTime.MinValue, current.Start.AddTicks(-1));
            TimeGapCalculator <TimeRange> gapCalculator    = new TimeGapCalculator <TimeRange>(calendar);
            ITimePeriodCollection         remainingPeriods = gapCalculator.GetGaps(ExcludePeriods, limits);

            return(remainingPeriods.Count > 0 ? new Week(remainingPeriods[remainingPeriods.Count - 1].End) : null);
        }         // FindPreviousWeek
Esempio n. 3
0
        }         // CalculateEnd

        // ----------------------------------------------------------------------
        private Week FindNextWeek(Week current)
        {
            if (ExcludePeriods.Count == 0)
            {
                return(current.GetNextWeek());
            }

            TimeRange limits = new TimeRange(current.End.AddTicks(1), DateTime.MaxValue);
            TimeGapCalculator <TimeRange> gapCalculator    = new TimeGapCalculator <TimeRange>(calendar);
            ITimePeriodCollection         remainingPeriods = gapCalculator.GetGaps(ExcludePeriods, limits);

            return(remainingPeriods.Count > 0 ? new Week(remainingPeriods[0].Start) : null);
        }         // FindNextWeek
Esempio n. 4
0
        }         // Add

        // ----------------------------------------------------------------------
        protected DateTime?CalculateEnd(DateTime start, TimeSpan offset,
                                        SeekDirection seekDirection, SeekBoundaryMode seekBoundaryMode, out TimeSpan?remaining)
        {
            if (offset < TimeSpan.Zero)
            {
                throw new InvalidOperationException("time span must be positive");
            }

            remaining = offset;

            // search periods
            TimePeriodCollection searchPeriods = new TimePeriodCollection(includePeriods);

            // no search periods specified: search anytime
            if (searchPeriods.Count == 0)
            {
                searchPeriods.Add(TimeRange.Anytime);
            }

            // available periods
            ITimePeriodCollection availablePeriods = new TimePeriodCollection();

            // no exclude periods specified: use all search periods
            if (excludePeriods.Count == 0)
            {
                availablePeriods.AddAll(searchPeriods);
            }
            else             // remove exclude periods
            {
                TimeGapCalculator <TimeRange> gapCalculator = new TimeGapCalculator <TimeRange>();
                foreach (ITimePeriod searchPeriod in searchPeriods)
                {
                    // no overlaps: use the entire search range
                    if (!excludePeriods.HasOverlapPeriods(searchPeriod))
                    {
                        availablePeriods.Add(searchPeriod);
                    }
                    else                     // add gaps of search period using the exclude periods
                    {
                        availablePeriods.AddAll(gapCalculator.GetGaps(excludePeriods, searchPeriod));
                    }
                }
            }

            // no periods available
            if (availablePeriods.Count == 0)
            {
                return(null);
            }

            // combine the available periods, ensure no overlapping
            // used for FindNextPeriod/FindPreviousPeriod
            if (availablePeriods.Count > 1)
            {
                TimePeriodCombiner <TimeRange> periodCombiner = new TimePeriodCombiner <TimeRange>();
                availablePeriods = periodCombiner.CombinePeriods(availablePeriods);
            }

            // find the starting search period
            ITimePeriod startPeriod = null;
            DateTime    seekMoment  = start;

            switch (seekDirection)
            {
            case SeekDirection.Forward:
                startPeriod = FindNextPeriod(start, availablePeriods, out seekMoment);
                break;

            case SeekDirection.Backward:
                startPeriod = FindPreviousPeriod(start, availablePeriods, out seekMoment);
                break;
            }

            // no starting period available
            if (startPeriod == null)
            {
                return(null);
            }

            // no offset: use the search staring position
            // maybe moved to the next available search period
            if (offset == TimeSpan.Zero)
            {
                return(seekMoment);
            }

            // setup destination search
            switch (seekDirection)
            {
            case SeekDirection.Forward:
                for (int i = availablePeriods.IndexOf(startPeriod); i < availablePeriods.Count; i++)
                {
                    ITimePeriod gap         = availablePeriods[i];
                    TimeSpan    gapRemining = gap.End - seekMoment;

                    bool isTargetPeriod = false;
                    switch (seekBoundaryMode)
                    {
                    case SeekBoundaryMode.Fill:
                        isTargetPeriod = gapRemining >= remaining;
                        break;

                    case SeekBoundaryMode.Next:
                        isTargetPeriod = gapRemining > remaining;
                        break;
                    }

                    if (isTargetPeriod)
                    {
                        DateTime end = seekMoment + remaining.Value;
                        remaining = null;
                        return(end);
                    }

                    remaining = remaining - gapRemining;
                    if (i == availablePeriods.Count - 1)
                    {
                        return(null);
                    }
                    seekMoment = availablePeriods[i + 1].Start;                               // next period
                }
                break;

            case SeekDirection.Backward:
                for (int i = availablePeriods.IndexOf(startPeriod); i >= 0; i--)
                {
                    ITimePeriod gap         = availablePeriods[i];
                    TimeSpan    gapRemining = seekMoment - gap.Start;

                    bool isTargetPeriod = false;
                    switch (seekBoundaryMode)
                    {
                    case SeekBoundaryMode.Fill:
                        isTargetPeriod = gapRemining >= remaining;
                        break;

                    case SeekBoundaryMode.Next:
                        isTargetPeriod = gapRemining > remaining;
                        break;
                    }

                    if (isTargetPeriod)
                    {
                        DateTime end = seekMoment - remaining.Value;
                        remaining = null;
                        return(end);
                    }
                    remaining = remaining - gapRemining;
                    if (i == 0)
                    {
                        return(null);
                    }
                    seekMoment = availablePeriods[i - 1].End;                               // previous period
                }
                break;
            }

            return(null);
        }         // CalculateEnd