public void NoPeriodsTest() { TimePeriodCombiner <TimeRange> periodCombiner = new TimePeriodCombiner <TimeRange>(); ITimePeriodCollection periods = periodCombiner.CombinePeriods(new TimePeriodCollection()); Assert.AreEqual(periods.Count, 0); } // NoPeriodsTest
public void MomentTest() { var period = new TimeRange(new DateTime(2011, 3, 1), new DateTime(2011, 3, 1)); var periodCombiner = new TimePeriodCombiner<TimeRange>(); var periods = periodCombiner.CombinePeriods(new TimePeriodCollection { period }); periods.Count.Should().Be(1); Assert.IsTrue(periods[0].IsSamePeriod(period)); }
public void TwoPeriodsOverlap1Test() { var period1 = new TimeRange(new DateTime(2011, 3, 1), new DateTime(2011, 3, 15)); var period2 = new TimeRange(new DateTime(2011, 3, 10), new DateTime(2011, 3, 20)); var periodCombiner = new TimePeriodCombiner<TimeRange>(); var periods = periodCombiner.CombinePeriods(period1, period2); periods.Count.Should().Be(1); Assert.IsTrue(periods[0].IsSamePeriod(new TimeRange(new DateTime(2011, 3, 1), new DateTime(2011, 3, 20)))); }
public void MomentTest() { TimeRange period = new TimeRange( new DateTime( 2011, 3, 1 ), new DateTime( 2011, 3, 1 ) ); TimePeriodCombiner<TimeRange> periodCombiner = new TimePeriodCombiner<TimeRange>(); ITimePeriodCollection periods = periodCombiner.CombinePeriods( new TimePeriodCollection { period } ); Assert.AreEqual( periods.Count, 1 ); Assert.IsTrue( periods[ 0 ].IsSamePeriod( period ) ); }
public void NoPeriodsTest() { var periodCombiner = new TimePeriodCombiner <TimeRange>(); var periods = periodCombiner.CombinePeriods(new TimePeriodCollection()); periods.Count.Should().Be(0); }
public void TwoPeriodsOverlap1Test() { var period1 = new TimeRange(new DateTime(2011, 3, 1), new DateTime(2011, 3, 15)); var period2 = new TimeRange(new DateTime(2011, 3, 10), new DateTime(2011, 3, 20)); var periodCombiner = new TimePeriodCombiner <TimeRange>(); var periods = periodCombiner.CombinePeriods(period1, period2); periods.Count.Should().Be(1); Assert.IsTrue(periods[0].IsSamePeriod(new TimeRange(new DateTime(2011, 3, 1), new DateTime(2011, 3, 20)))); }
public void SinglePeriodAnytimeTest() { TimePeriodCombiner <TimeRange> periodCombiner = new TimePeriodCombiner <TimeRange>(); ITimePeriodCollection periods = periodCombiner.CombinePeriods(new TimePeriodCollection { TimeRange.Anytime }); Assert.AreEqual(periods.Count, 1); Assert.IsTrue(periods[0].IsSamePeriod(TimeRange.Anytime)); } // SinglePeriodAnytimeTest
public void SinglePeriodAnytimeTest() { var periodCombiner = new TimePeriodCombiner <TimeRange>(); var periods = periodCombiner.CombinePeriods(new TimePeriodCollection { TimeRange.Anytime }); periods.Count.Should().Be(1); Assert.IsTrue(periods[0].IsSamePeriod(TimeRange.Anytime)); }
public void SinglePeriodTest() { TimeRange period = new TimeRange(new DateTime(2011, 3, 1), new DateTime(2011, 3, 5)); TimePeriodCombiner <TimeRange> periodCombiner = new TimePeriodCombiner <TimeRange>(); ITimePeriodCollection periods = periodCombiner.CombinePeriods(new TimePeriodCollection { period }); Assert.Equal(1, periods.Count); Assert.True(periods[0].IsSamePeriod(period)); } // SinglePeriodTest
public void MomentTest() { var period = new TimeRange(new DateTime(2011, 3, 1), new DateTime(2011, 3, 1)); var periodCombiner = new TimePeriodCombiner <TimeRange>(); var periods = periodCombiner.CombinePeriods(new TimePeriodCollection { period }); periods.Count.Should().Be(1); Assert.IsTrue(periods[0].IsSamePeriod(period)); }
public void MomentTest() { TimeRange period = new TimeRange(new DateTime(2011, 3, 1), new DateTime(2011, 3, 1)); TimePeriodCombiner <TimeRange> periodCombiner = new TimePeriodCombiner <TimeRange>(); ITimePeriodCollection periods = periodCombiner.CombinePeriods(new TimePeriodCollection { period }); Assert.AreEqual(periods.Count, 1); Assert.IsTrue(periods[0].IsSamePeriod(period)); } // MomentTest
public void TwoPeriodsInside2Test() { TimeRange period1 = new TimeRange(new DateTime(2011, 3, 5), new DateTime(2011, 3, 15)); TimeRange period2 = new TimeRange(new DateTime(2011, 3, 1), new DateTime(2011, 3, 20)); TimePeriodCombiner <TimeRange> periodCombiner = new TimePeriodCombiner <TimeRange>(); ITimePeriodCollection periods = periodCombiner.CombinePeriods(new TimePeriodCollection { period1, period2 }); Assert.Equal(1, periods.Count); Assert.True(periods[0].IsSamePeriod(new TimeRange(new DateTime(2011, 3, 1), new DateTime(2011, 3, 20)))); } // TwoPeriodsInside2Test
public void TwoPeriodsTouchingTest() { var period1 = new TimeRange(new DateTime(2011, 3, 1), new DateTime(2011, 3, 10)); var period2 = new TimeRange(new DateTime(2011, 3, 10), new DateTime(2011, 3, 20)); var periodCombiner = new TimePeriodCombiner<TimeRange>(); var periods = periodCombiner.CombinePeriods(new TimePeriodCollection { period1, period2 }); periods.Count.Should().Be(1); Assert.IsTrue(periods[0].IsSamePeriod(new TimeRange(new DateTime(2011, 3, 1), new DateTime(2011, 3, 20)))); }
public void TwoPeriodsTouchingTest() { TimeRange period1 = new TimeRange(new DateTime(2011, 3, 1), new DateTime(2011, 3, 10)); TimeRange period2 = new TimeRange(new DateTime(2011, 3, 10), new DateTime(2011, 3, 20)); TimePeriodCombiner <TimeRange> periodCombiner = new TimePeriodCombiner <TimeRange>(); ITimePeriodCollection periods = periodCombiner.CombinePeriods(new TimePeriodCollection { period1, period2 }); Assert.AreEqual(periods.Count, 1); Assert.IsTrue(periods[0].IsSamePeriod(new TimeRange(new DateTime(2011, 3, 1), new DateTime(2011, 3, 20)))); } // TwoPeriodsTouchingTest
public void Pattern1Test() { TimeRange period1 = new TimeRange( new DateTime( 2011, 3, 01 ), new DateTime( 2011, 3, 05 ) ); TimeRange period2 = new TimeRange( new DateTime( 2011, 3, 05 ), new DateTime( 2011, 3, 10 ) ); TimeRange period3 = new TimeRange( new DateTime( 2011, 3, 10 ), new DateTime( 2011, 3, 15 ) ); TimeRange period4 = new TimeRange( new DateTime( 2011, 3, 15 ), new DateTime( 2011, 3, 20 ) ); TimeRange period5 = new TimeRange( new DateTime( 2011, 3, 20 ), new DateTime( 2011, 3, 25 ) ); TimePeriodCombiner<TimeRange> periodCombiner = new TimePeriodCombiner<TimeRange>(); ITimePeriodCollection periods = periodCombiner.CombinePeriods( new TimePeriodCollection { period1, period2, period3, period4, period5 } ); Assert.AreEqual( periods.Count, 1 ); Assert.IsTrue( periods[ 0 ].IsSamePeriod( new TimeRange( new DateTime( 2011, 3, 1 ), new DateTime( 2011, 3, 25 ) ) ) ); }
public void Pattern3Test() { var period1 = new TimeRange(new DateTime(2011, 3, 01), new DateTime(2011, 3, 05)); var period2 = new TimeRange(new DateTime(2011, 3, 01), new DateTime(2011, 3, 10)); var period3 = new TimeRange(new DateTime(2011, 3, 01), new DateTime(2011, 3, 15)); var period4 = new TimeRange(new DateTime(2011, 3, 01), new DateTime(2011, 3, 20)); var period5 = new TimeRange(new DateTime(2011, 3, 01), new DateTime(2011, 3, 25)); var periodCombiner = new TimePeriodCombiner <TimeRange>(); var periods = periodCombiner.CombinePeriods(period1, period2, period3, period4, period5); periods.Count.Should().Be(1); Assert.IsTrue(periods[0].IsSamePeriod(new TimeRange(new DateTime(2011, 3, 1), new DateTime(2011, 3, 25)))); }
public void TwoPeriodsTouchingTest() { var period1 = new TimeRange(new DateTime(2011, 3, 1), new DateTime(2011, 3, 10)); var period2 = new TimeRange(new DateTime(2011, 3, 10), new DateTime(2011, 3, 20)); var periodCombiner = new TimePeriodCombiner <TimeRange>(); var periods = periodCombiner.CombinePeriods(new TimePeriodCollection { period1, period2 }); periods.Count.Should().Be(1); Assert.IsTrue(periods[0].IsSamePeriod(new TimeRange(new DateTime(2011, 3, 1), new DateTime(2011, 3, 20)))); }
public void Pattern4Test() { TimeRange period1 = new TimeRange(new DateTime(2011, 3, 20), new DateTime(2011, 3, 25)); TimeRange period2 = new TimeRange(new DateTime(2011, 3, 15), new DateTime(2011, 3, 25)); TimeRange period3 = new TimeRange(new DateTime(2011, 3, 10), new DateTime(2011, 3, 25)); TimeRange period4 = new TimeRange(new DateTime(2011, 3, 05), new DateTime(2011, 3, 25)); TimeRange period5 = new TimeRange(new DateTime(2011, 3, 01), new DateTime(2011, 3, 25)); TimePeriodCombiner <TimeRange> periodCombiner = new TimePeriodCombiner <TimeRange>(); ITimePeriodCollection periods = periodCombiner.CombinePeriods(new TimePeriodCollection { period1, period2, period3, period4, period5 }); Assert.AreEqual(periods.Count, 1); Assert.IsTrue(periods[0].IsSamePeriod(new TimeRange(new DateTime(2011, 3, 1), new DateTime(2011, 3, 25)))); } // Pattern4Test
public static bool NeedPause(this PlanItem dienst, out int pause) { pause = 0; if (dienst.Zeitraum.Duration.NeedPause()) { pause = 30; return(true); } //wenn keine Pause aber Großteam noch ist if (dienst.HatGrossteam) { var tp = new TimePeriodCollection(new List <ITimePeriod>() { dienst.Zeitraum, dienst.Arbeitstag.Grossteam }); if (tp.HasGaps()) { var gapCalculator = new TimeGapCalculator <TimeRange>(new TimeCalendar()); var gaps = gapCalculator.GetGaps(tp); var gap = (int)Math.Round(gaps.First().Duration.TotalMinutes, MidpointRounding.ToEven); //sollte nur eine geben, sind ja nur 2 Zeiten if (gap < 30) { pause = 30 - gap; return(true); } } else { var periodCombiner = new TimePeriodCombiner <TimeRange>(); var combinedPeriods = periodCombiner.CombinePeriods(tp); if (combinedPeriods.First().Duration.NeedPause()) { pause = 30; return(true); } } } return(false); }
public void Pattern6Test() { var period1 = new TimeRange(new DateTime(2011, 3, 01), new DateTime(2011, 3, 10)); var period2 = new TimeRange(new DateTime(2011, 3, 04), new DateTime(2011, 3, 08)); var period3 = new TimeRange(new DateTime(2011, 3, 15), new DateTime(2011, 3, 18)); var period4 = new TimeRange(new DateTime(2011, 3, 18), new DateTime(2011, 3, 22)); var period5 = new TimeRange(new DateTime(2011, 3, 20), new DateTime(2011, 3, 24)); var period6 = new TimeRange(new DateTime(2011, 3, 26), new DateTime(2011, 3, 30)); var periodCombiner = new TimePeriodCombiner <TimeRange>(); var periods = periodCombiner.CombinePeriods(period1, period2, period3, period4, period5, period6); periods.Count.Should().Be(3); Assert.IsTrue(periods[0].IsSamePeriod(new TimeRange(new DateTime(2011, 3, 01), new DateTime(2011, 3, 10)))); Assert.IsTrue(periods[1].IsSamePeriod(new TimeRange(new DateTime(2011, 3, 15), new DateTime(2011, 3, 24)))); Assert.IsTrue(periods[2].IsSamePeriod(new TimeRange(new DateTime(2011, 3, 26), new DateTime(2011, 3, 30)))); }
public void Pattern6Test() { TimeRange period1 = new TimeRange(new DateTime(2011, 3, 01), new DateTime(2011, 3, 10)); TimeRange period2 = new TimeRange(new DateTime(2011, 3, 04), new DateTime(2011, 3, 08)); TimeRange period3 = new TimeRange(new DateTime(2011, 3, 15), new DateTime(2011, 3, 18)); TimeRange period4 = new TimeRange(new DateTime(2011, 3, 18), new DateTime(2011, 3, 22)); TimeRange period5 = new TimeRange(new DateTime(2011, 3, 20), new DateTime(2011, 3, 24)); TimeRange period6 = new TimeRange(new DateTime(2011, 3, 26), new DateTime(2011, 3, 30)); TimePeriodCombiner <TimeRange> periodCombiner = new TimePeriodCombiner <TimeRange>(); ITimePeriodCollection periods = periodCombiner.CombinePeriods(new TimePeriodCollection { period1, period2, period3, period4, period5, period6 }); Assert.AreEqual(periods.Count, 3); Assert.IsTrue(periods[0].IsSamePeriod(new TimeRange(new DateTime(2011, 3, 01), new DateTime(2011, 3, 10)))); Assert.IsTrue(periods[1].IsSamePeriod(new TimeRange(new DateTime(2011, 3, 15), new DateTime(2011, 3, 24)))); Assert.IsTrue(periods[2].IsSamePeriod(new TimeRange(new DateTime(2011, 3, 26), new DateTime(2011, 3, 30)))); } // Pattern6Test
public void CombinePeriodsIsssue9() { // Combine Periods List <TimeRange> timeRanges = new List <TimeRange>() { new TimeRange() { Start = new DateTime(2016, 01, 01), End = new DateTime(2016, 01, 01) }, new TimeRange() { Start = new DateTime(2016, 12, 31), End = new DateTime(2016, 12, 31) } }; TimePeriodCollection periods = new TimePeriodCollection(timeRanges); TimePeriodCombiner <TimeRange> periodCombiner = new TimePeriodCombiner <TimeRange>(); ITimePeriodCollection combinedPeriods = periodCombiner.CombinePeriods(periods); Assert.Equal(0, combinedPeriods.Count); }
/// <summary> /// Get vacant time slots from Italki, shredded as sessions /// </summary> /// <returns></returns> public static async Task <IEnumerable <SessionDto> > GetOfferedSchedules(DateTime startDate, DateTime endDate, bool forceRealTime) { // Load all the HTML pages simultaneously. var tasks = ItalkiTeachers.Select(i => GetTeacherPeriods(i.UserId, forceRealTime)); var teacherPeriodsArray = await Task.WhenAll(tasks); // italki does not allow booking in less than 24 hour. var threshold = GetBookingTimeThreshold(); var allPeriods = teacherPeriodsArray // Flatten all lists .SelectMany(i => i) // Filter .Where(i => (i.Start < endDate) && (i.End > startDate) && // There may be 30-minute "left over" slots available. We filter them out. Our sessions are 60 minutes. (i.Duration >= SessionDuration) && (i.End >= threshold + SessionDuration) ) ; // Merge all periods for display. ITimePeriodCollection periodCollection = new TimePeriodCollection(); var periodCombiner = new TimePeriodCombiner <TeacherTimeRange>(); periodCollection.AddAll(allPeriods); periodCollection = periodCombiner.CombinePeriods(periodCollection); var offeredSessions = periodCollection .Select(i => new SessionDto { Start = i.Start >= threshold ? i.Start : threshold, End = i.End, }); return(offeredSessions); }
} // GapCalculator32 // ---------------------------------------------------------------------- public void Combiner5(int count) { TimeRange period1 = new TimeRange(new DateTime(2011, 3, 01), new DateTime(2011, 3, 05)); TimeRange period2 = new TimeRange(new DateTime(2011, 3, 01), new DateTime(2011, 3, 10)); TimeRange period3 = new TimeRange(new DateTime(2011, 3, 01), new DateTime(2011, 3, 15)); TimeRange period4 = new TimeRange(new DateTime(2011, 3, 01), new DateTime(2011, 3, 20)); TimeRange period5 = new TimeRange(new DateTime(2011, 3, 01), new DateTime(2011, 3, 25)); TimePeriodCombiner <TimeRange> periodCombiner = new TimePeriodCombiner <TimeRange>(); Console.Write("Combiner 5 ({0:#,0}): ", count); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); for (int i = 0; i < count; i++) { periodCombiner.CombinePeriods(new TimePeriodCollection { period1, period2, period3, period4, period5 }); } stopwatch.Stop(); Console.WriteLine(" {0} ms", stopwatch.ElapsedMilliseconds); } // Combiner5
// ---------------------------------------------------------------------- public void TimePeriodCombinerSample() { TimePeriodCollection periods = new TimePeriodCollection(); periods.Add(new TimeRange(new DateTime(2011, 3, 01), new DateTime(2011, 3, 10))); periods.Add(new TimeRange(new DateTime(2011, 3, 04), new DateTime(2011, 3, 08))); periods.Add(new TimeRange(new DateTime(2011, 3, 15), new DateTime(2011, 3, 18))); periods.Add(new TimeRange(new DateTime(2011, 3, 18), new DateTime(2011, 3, 22))); periods.Add(new TimeRange(new DateTime(2011, 3, 20), new DateTime(2011, 3, 24))); periods.Add(new TimeRange(new DateTime(2011, 3, 26), new DateTime(2011, 3, 30))); TimePeriodCombiner <TimeRange> periodCombiner = new TimePeriodCombiner <TimeRange>(); ITimePeriodCollection combinedPeriods = periodCombiner.CombinePeriods(periods); foreach (ITimePeriod combinedPeriod in combinedPeriods) { Console.WriteLine("Combined Period: " + combinedPeriod); } // > Combined Period: 01.03.2011 - 10.03.2011 | 9.00:00 // > Combined Period: 15.03.2011 - 24.03.2011 | 9.00:00 // > Combined Period: 26.03.2011 - 30.03.2011 | 4.00:00 } // TimePeriodCombinerSample
public void SinglePeriodAnytimeTest() { TimePeriodCombiner<TimeRange> periodCombiner = new TimePeriodCombiner<TimeRange>(); ITimePeriodCollection periods = periodCombiner.CombinePeriods( new TimePeriodCollection { TimeRange.Anytime } ); Assert.AreEqual( periods.Count, 1 ); Assert.IsTrue( periods[ 0 ].IsSamePeriod( TimeRange.Anytime ) ); }
public void Pattern5Test() { var period1 = new TimeRange(new DateTime(2011, 3, 01), new DateTime(2011, 3, 05)); var period2 = new TimeRange(new DateTime(2011, 3, 01), new DateTime(2011, 3, 10)); var period3 = new TimeRange(new DateTime(2011, 3, 01), new DateTime(2011, 3, 15)); var period4 = new TimeRange(new DateTime(2011, 3, 05), new DateTime(2011, 3, 25)); var period5 = new TimeRange(new DateTime(2011, 3, 10), new DateTime(2011, 3, 25)); var period6 = new TimeRange(new DateTime(2011, 3, 15), new DateTime(2011, 3, 25)); var periodCombiner = new TimePeriodCombiner<TimeRange>(); var periods = periodCombiner.CombinePeriods(period1, period2, period3, period4, period5, period6); periods.Count.Should().Be(1); Assert.IsTrue(periods[0].IsSamePeriod(new TimeRange(new DateTime(2011, 3, 1), new DateTime(2011, 3, 25)))); }
public void Pattern6Test() { var period1 = new TimeRange(new DateTime(2011, 3, 01), new DateTime(2011, 3, 10)); var period2 = new TimeRange(new DateTime(2011, 3, 04), new DateTime(2011, 3, 08)); var period3 = new TimeRange(new DateTime(2011, 3, 15), new DateTime(2011, 3, 18)); var period4 = new TimeRange(new DateTime(2011, 3, 18), new DateTime(2011, 3, 22)); var period5 = new TimeRange(new DateTime(2011, 3, 20), new DateTime(2011, 3, 24)); var period6 = new TimeRange(new DateTime(2011, 3, 26), new DateTime(2011, 3, 30)); var periodCombiner = new TimePeriodCombiner<TimeRange>(); var periods = periodCombiner.CombinePeriods(period1, period2, period3, period4, period5, period6); periods.Count.Should().Be(3); Assert.IsTrue(periods[0].IsSamePeriod(new TimeRange(new DateTime(2011, 3, 01), new DateTime(2011, 3, 10)))); Assert.IsTrue(periods[1].IsSamePeriod(new TimeRange(new DateTime(2011, 3, 15), new DateTime(2011, 3, 24)))); Assert.IsTrue(periods[2].IsSamePeriod(new TimeRange(new DateTime(2011, 3, 26), new DateTime(2011, 3, 30)))); }
/// <summary> /// <paramref name="start"/>시각으로부터 <paramref name="offset"/> 만큼 떨어진 시각을 구합니다. /// </summary> /// <param name="start">기준 시각</param> /// <param name="offset">기간</param> /// <param name="seekDirection">검색 방향 (이전|이후)</param> /// <param name="seekBoundaryMode">검색 값 포함 여부</param> /// <param name="remaining">짜투리 기간</param> /// <returns>기준 시각으로터 오프셋만큼 떨어진 시각</returns> protected DateTime? CalculateEnd(DateTime start, TimeSpan offset, SeekDirection seekDirection, SeekBoundaryMode seekBoundaryMode, out TimeSpan? remaining) { if(IsDebugEnabled) log.Debug("기준시각으로부터 오프셋만큼 떨어진 시각을 구합니다... " + @"start=[{0}], offset=[{1}], seekDirection=[{2}], seekBoundaryMode=[{3}]", start, offset, seekDirection, seekBoundaryMode); Guard.Assert(offset >= TimeSpan.Zero, "offset 값은 항상 0 이상이어야 합니다. offset=[{0}]", offset); remaining = offset; // search periods ITimePeriodCollection searchPeriods = new TimePeriodCollection(IncludePeriods); if(searchPeriods.Count == 0) searchPeriods.Add(TimeRange.Anytime); // available periods ITimePeriodCollection availablePeriods = new TimePeriodCollection(); if(ExcludePeriods.Count == 0) { availablePeriods.AddAll(searchPeriods); } else { // 예외 기간을 제외합니다. // var gapCalculator = new TimeGapCalculator<TimeRange>(); var query = searchPeriods #if !SILVERLIGHT .AsParallel() .AsOrdered() #endif .SelectMany(searchPeriod => ExcludePeriods.HasOverlapPeriods(searchPeriod) ? gapCalculator.GetGaps(ExcludePeriods, searchPeriod) // 예외 기간과 검색 기간에서 겹치지 않는 기간을 계산하여, 추려냅니다. : new TimePeriodCollection { searchPeriod } // 예외 기간과 겹쳐진 부분이 없다면, 기간 전체를 추가합니다. ); availablePeriods.AddAll(query); } // 유효한 Period가 없다면 중단합니다. if(availablePeriods.Count == 0) return null; // 기간중에 중복되는 부분의 없도록 유효한 기간을 결합합니다. if(availablePeriods.Count > 1) { var periodCombiner = new TimePeriodCombiner<TimeRange>(); availablePeriods = periodCombiner.CombinePeriods(availablePeriods); } // 첫 시작 기간을 찾습니다. // DateTime seekMoment; var startPeriod = (seekDirection == SeekDirection.Forward) ? FindNextPeriod(start, availablePeriods, out seekMoment) : FindPreviousPeriod(start, availablePeriods, out seekMoment); // 첫 시작 기간이 없다면 중단합니다. if(startPeriod == null) return null; // 오프셋 값이 0 이라면, 바로 다음 값이므로 seekMoment를 반환합니다. if(offset == TimeSpan.Zero) return seekMoment; if(seekDirection == SeekDirection.Forward) { for(var i = availablePeriods.IndexOf(startPeriod); i < availablePeriods.Count; i++) { var gap = availablePeriods[i]; var gapRemaining = gap.End - seekMoment; if(IsDebugEnabled) log.Debug("Seek Forward... gap=[{0}], gapRemaining=[{1}], remaining=[{2}], seekMoment=[{3}]", gap, gapRemaining, remaining, seekMoment); var isTargetPeriod = (seekBoundaryMode == SeekBoundaryMode.Fill) ? gapRemaining >= remaining : gapRemaining > remaining; if(isTargetPeriod) { var end = seekMoment + remaining.Value; remaining = null; return end; } remaining = remaining - gapRemaining; if(i == availablePeriods.Count - 1) return null; seekMoment = availablePeriods[i + 1].Start; // next period } } else { for(var i = availablePeriods.IndexOf(startPeriod); i >= 0; i--) { var gap = availablePeriods[i]; var gapRemaining = seekMoment - gap.Start; if(IsDebugEnabled) log.Debug("Seek Backward... gap=[{0}], gapRemaining=[{1}], remaining=[{2}], seekMoment=[{3}]", gap, gapRemaining, remaining, seekMoment); var isTargetPeriod = (seekBoundaryMode == SeekBoundaryMode.Fill) ? gapRemaining >= remaining : gapRemaining > remaining; if(isTargetPeriod) { var end = seekMoment - remaining.Value; remaining = null; return end; } remaining = remaining - gapRemaining; if(i == 0) return null; seekMoment = availablePeriods[i - 1].End; // previous period } } return null; }
// ---------------------------------------------------------------------- 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; }
public void NoPeriodsTest() { var periodCombiner = new TimePeriodCombiner<TimeRange>(); var periods = periodCombiner.CombinePeriods(new TimePeriodCollection()); periods.Count.Should().Be(0); }
public void NoPeriodsTest() { TimePeriodCombiner<TimeRange> periodCombiner = new TimePeriodCombiner<TimeRange>(); ITimePeriodCollection periods = periodCombiner.CombinePeriods( new TimePeriodCollection() ); Assert.AreEqual( periods.Count, 0 ); }
public void TimePeriodCombinerSample() { TimePeriodCollection periods = new TimePeriodCollection(); periods.Add( new TimeRange( new DateTime( 2011, 3, 01 ), new DateTime( 2011, 3, 10 ) ) ); periods.Add( new TimeRange( new DateTime( 2011, 3, 04 ), new DateTime( 2011, 3, 08 ) ) ); periods.Add( new TimeRange( new DateTime( 2011, 3, 15 ), new DateTime( 2011, 3, 18 ) ) ); periods.Add( new TimeRange( new DateTime( 2011, 3, 18 ), new DateTime( 2011, 3, 22 ) ) ); periods.Add( new TimeRange( new DateTime( 2011, 3, 20 ), new DateTime( 2011, 3, 24 ) ) ); periods.Add( new TimeRange( new DateTime( 2011, 3, 26 ), new DateTime( 2011, 3, 30 ) ) ); TimePeriodCombiner<TimeRange> periodCombiner = new TimePeriodCombiner<TimeRange>(); ITimePeriodCollection combinedPeriods = periodCombiner.CombinePeriods( periods ); foreach ( ITimePeriod combinedPeriod in combinedPeriods ) { Console.WriteLine( "Combined Period: " + combinedPeriod ); } // > Combined Period: 01.03.2011 - 10.03.2011 | 9.00:00 // > Combined Period: 15.03.2011 - 24.03.2011 | 9.00:00 // > Combined Period: 26.03.2011 - 30.03.2011 | 4.00:00 }
public void SinglePeriodAnytimeTest() { var periodCombiner = new TimePeriodCombiner<TimeRange>(); var periods = periodCombiner.CombinePeriods(new TimePeriodCollection { TimeRange.Anytime }); periods.Count.Should().Be(1); Assert.IsTrue(periods[0].IsSamePeriod(TimeRange.Anytime)); }
/// <summary> /// <paramref name="start"/>시각으로부터 <paramref name="offset"/> 만큼 떨어진 시각을 구합니다. /// </summary> /// <param name="start">기준 시각</param> /// <param name="offset">기간</param> /// <param name="seekDirection">검색 방향 (이전|이후)</param> /// <param name="seekBoundaryMode">검색 값 포함 여부</param> /// <param name="remaining">짜투리 기간</param> /// <returns>기준 시각으로터 오프셋만큼 떨어진 시각</returns> protected DateTime?CalculateEnd(DateTime start, TimeSpan offset, SeekDirection seekDirection, SeekBoundaryMode seekBoundaryMode, out TimeSpan?remaining) { if (IsDebugEnabled) { log.Debug("기준시각으로부터 오프셋만큼 떨어진 시각을 구합니다... " + @"start=[{0}], offset=[{1}], seekDirection=[{2}], seekBoundaryMode=[{3}]", start, offset, seekDirection, seekBoundaryMode); } Guard.Assert(offset >= TimeSpan.Zero, "offset 값은 항상 0 이상이어야 합니다. offset=[{0}]", offset); remaining = offset; // search periods ITimePeriodCollection searchPeriods = new TimePeriodCollection(IncludePeriods); if (searchPeriods.Count == 0) { searchPeriods.Add(TimeRange.Anytime); } // available periods ITimePeriodCollection availablePeriods = new TimePeriodCollection(); if (ExcludePeriods.Count == 0) { availablePeriods.AddAll(searchPeriods); } else { // 예외 기간을 제외합니다. // var gapCalculator = new TimeGapCalculator <TimeRange>(); var query = searchPeriods #if !SILVERLIGHT .AsParallel() .AsOrdered() #endif .SelectMany(searchPeriod => ExcludePeriods.HasOverlapPeriods(searchPeriod) ? gapCalculator.GetGaps(ExcludePeriods, searchPeriod) // 예외 기간과 검색 기간에서 겹치지 않는 기간을 계산하여, 추려냅니다. : new TimePeriodCollection { searchPeriod } // 예외 기간과 겹쳐진 부분이 없다면, 기간 전체를 추가합니다. ); availablePeriods.AddAll(query); } // 유효한 Period가 없다면 중단합니다. if (availablePeriods.Count == 0) { return(null); } // 기간중에 중복되는 부분의 없도록 유효한 기간을 결합합니다. if (availablePeriods.Count > 1) { var periodCombiner = new TimePeriodCombiner <TimeRange>(); availablePeriods = periodCombiner.CombinePeriods(availablePeriods); } // 첫 시작 기간을 찾습니다. // DateTime seekMoment; var startPeriod = (seekDirection == SeekDirection.Forward) ? FindNextPeriod(start, availablePeriods, out seekMoment) : FindPreviousPeriod(start, availablePeriods, out seekMoment); // 첫 시작 기간이 없다면 중단합니다. if (startPeriod == null) { return(null); } // 오프셋 값이 0 이라면, 바로 다음 값이므로 seekMoment를 반환합니다. if (offset == TimeSpan.Zero) { return(seekMoment); } if (seekDirection == SeekDirection.Forward) { for (var i = availablePeriods.IndexOf(startPeriod); i < availablePeriods.Count; i++) { var gap = availablePeriods[i]; var gapRemaining = gap.End - seekMoment; if (IsDebugEnabled) { log.Debug("Seek Forward... gap=[{0}], gapRemaining=[{1}], remaining=[{2}], seekMoment=[{3}]", gap, gapRemaining, remaining, seekMoment); } var isTargetPeriod = (seekBoundaryMode == SeekBoundaryMode.Fill) ? gapRemaining >= remaining : gapRemaining > remaining; if (isTargetPeriod) { var end = seekMoment + remaining.Value; remaining = null; return(end); } remaining = remaining - gapRemaining; if (i == availablePeriods.Count - 1) { return(null); } seekMoment = availablePeriods[i + 1].Start; // next period } } else { for (var i = availablePeriods.IndexOf(startPeriod); i >= 0; i--) { var gap = availablePeriods[i]; var gapRemaining = seekMoment - gap.Start; if (IsDebugEnabled) { log.Debug("Seek Backward... gap=[{0}], gapRemaining=[{1}], remaining=[{2}], seekMoment=[{3}]", gap, gapRemaining, remaining, seekMoment); } var isTargetPeriod = (seekBoundaryMode == SeekBoundaryMode.Fill) ? gapRemaining >= remaining : gapRemaining > remaining; if (isTargetPeriod) { var end = seekMoment - remaining.Value; remaining = null; return(end); } remaining = remaining - gapRemaining; if (i == 0) { return(null); } seekMoment = availablePeriods[i - 1].End; // previous period } } return(null); }
public void Pattern6Test() { TimeRange period1 = new TimeRange( new DateTime( 2011, 3, 01 ), new DateTime( 2011, 3, 10 ) ); TimeRange period2 = new TimeRange( new DateTime( 2011, 3, 04 ), new DateTime( 2011, 3, 08 ) ); TimeRange period3 = new TimeRange( new DateTime( 2011, 3, 15 ), new DateTime( 2011, 3, 18 ) ); TimeRange period4 = new TimeRange( new DateTime( 2011, 3, 18 ), new DateTime( 2011, 3, 22 ) ); TimeRange period5 = new TimeRange( new DateTime( 2011, 3, 20 ), new DateTime( 2011, 3, 24 ) ); TimeRange period6 = new TimeRange( new DateTime( 2011, 3, 26 ), new DateTime( 2011, 3, 30 ) ); TimePeriodCombiner<TimeRange> periodCombiner = new TimePeriodCombiner<TimeRange>(); ITimePeriodCollection periods = periodCombiner.CombinePeriods( new TimePeriodCollection { period1, period2, period3, period4, period5, period6 } ); Assert.AreEqual( periods.Count, 3 ); Assert.IsTrue( periods[ 0 ].IsSamePeriod( new TimeRange( new DateTime( 2011, 3, 01 ), new DateTime( 2011, 3, 10 ) ) ) ); Assert.IsTrue( periods[ 1 ].IsSamePeriod( new TimeRange( new DateTime( 2011, 3, 15 ), new DateTime( 2011, 3, 24 ) ) ) ); Assert.IsTrue( periods[ 2 ].IsSamePeriod( new TimeRange( new DateTime( 2011, 3, 26 ), new DateTime( 2011, 3, 30 ) ) ) ); }
private ITimePeriodCollection CombinePeriods(ITimePeriodCollection periods) { var periodCombiner = new TimePeriodCombiner <TimeRange>(); return(periodCombiner.CombinePeriods(periods)); }
public void TwoPeriodsTouchingTest() { TimeRange period1 = new TimeRange( new DateTime( 2011, 3, 1 ), new DateTime( 2011, 3, 10 ) ); TimeRange period2 = new TimeRange( new DateTime( 2011, 3, 10 ), new DateTime( 2011, 3, 20 ) ); TimePeriodCombiner<TimeRange> periodCombiner = new TimePeriodCombiner<TimeRange>(); ITimePeriodCollection periods = periodCombiner.CombinePeriods( new TimePeriodCollection { period1, period2 } ); Assert.AreEqual( periods.Count, 1 ); Assert.IsTrue( periods[ 0 ].IsSamePeriod( new TimeRange( new DateTime( 2011, 3, 1 ), new DateTime( 2011, 3, 20 ) ) ) ); }