} // IntersectPeriods // ---------------------------------------------------------------------- public ITimePeriodCollection CalculateGaps() { // exclude periods TimePeriodCollection gapPeriods = new TimePeriodCollection(); foreach (ITimePeriod period in periods) { if (limits.IntersectsWith(period)) { gapPeriods.Add(new TimeRange(period)); } } ITimeLineMomentCollection timeLineMoments = GetTimeLineMoments(gapPeriods); if (timeLineMoments.Count == 0) { return(new TimePeriodCollection { limits }); } T range = new T(); range.Setup(MapPeriodStart(limits.Start), MapPeriodEnd(limits.End)); return(CalculateGaps(range, timeLineMoments)); } // CalculateGaps
} // GetTimeLineMoments // ---------------------------------------------------------------------- private static ITimePeriodCollection CombinePeriods(ITimeLineMomentCollection timeLineMoments) { TimePeriodCollection periods = new TimePeriodCollection(); if (timeLineMoments.IsEmpty) { return(periods); } // search for periods int itemIndex = 0; while (itemIndex < timeLineMoments.Count) { ITimeLineMoment periodStart = timeLineMoments[itemIndex]; int startCount = periodStart.StartCount; if (startCount == 0) { throw new InvalidOperationException(); } // search next period end // use balancing to handle overlapping periods int balance = startCount; ITimeLineMoment periodEnd = null; while (itemIndex < timeLineMoments.Count - 1 && balance > 0) { itemIndex++; periodEnd = timeLineMoments[itemIndex]; balance += periodEnd.BalanceCount; } if (periodEnd == null) { throw new InvalidOperationException(); } if (periodEnd.StartCount > 0) // touching { itemIndex++; continue; } // found a period if (itemIndex < timeLineMoments.Count) { T period = new T(); period.Setup(periodStart.Moment, periodEnd.Moment); periods.Add(period); } itemIndex++; } return(periods); } // CombinePeriods
} // Years // ---------------------------------------------------------------------- public ITimePeriodCollection GetYears() { TimePeriodCollection years = new TimePeriodCollection(); for (int i = 0; i < YearCount; i++) { years.Add(new Year(BaseYear + i, Calendar)); } return(years); } // GetYears
} // Weeks // ---------------------------------------------------------------------- public ITimePeriodCollection GetWeeks() { TimePeriodCollection weeks = new TimePeriodCollection(); for (int i = 0; i < WeekCount; i++) { weeks.Add(new Week(Year, StartWeek + i, Calendar)); } return(weeks); } // GetWeeks
} // GetWeeks // ---------------------------------------------------------------------- public ITimePeriodCollection GetMonths() { TimePeriodCollection months = new TimePeriodCollection(); for (int month = 1; month <= TimeSpec.MonthsPerYear; month++) { months.Add(new BroadcastMonth(year, (YearMonth)month)); } return(months); } // GetMonths
} // Year // ---------------------------------------------------------------------- public ITimePeriodCollection GetWeeks() { TimePeriodCollection weeks = new TimePeriodCollection(); int weekCount = BroadcastCalendarTool.GetWeeksOfYear(year); for (int week = 1; week <= weekCount; week++) { weeks.Add(new BroadcastWeek(year, week)); } return(weeks); } // GetWeeks
} // Hours // ---------------------------------------------------------------------- public ITimePeriodCollection GetHours() { TimePeriodCollection hours = new TimePeriodCollection(); DateTime startHour = new DateTime(StartYear, StartMonth, StartDay, StartHour, 0, 0); for (int i = 0; i < HourCount; i++) { hours.Add(new Hour(startHour.AddHours(i), Calendar)); } return(hours); } // GetHours
} // Minutes // ---------------------------------------------------------------------- public ITimePeriodCollection GetMinutes() { TimePeriodCollection minutes = new TimePeriodCollection(); DateTime startMinute = new DateTime(StartYear, StartMonth, StartDay, StartHour, StartMinute, 0); for (int i = 0; i < MinuteCount; i++) { minutes.Add(new Minute(startMinute.AddMinutes(i), Calendar)); } return(minutes); } // GetMinutes
} // Days // ---------------------------------------------------------------------- public ITimePeriodCollection GetDays() { TimePeriodCollection days = new TimePeriodCollection(); DateTime startDay = new DateTime(StartYear, StartMonth, StartDay); for (int i = 0; i < DayCount; i++) { days.Add(new Day(startDay.AddDays(i), Calendar)); } return(days); } // GetDays
} // GetStartOfWeek // ---------------------------------------------------------------------- public ITimePeriodCollection GetDays() { TimePeriodCollection days = new TimePeriodCollection(); DateTime startDate = TimeTool.GetStartOfYearWeek(year, startWeek, Calendar.Culture, Calendar.YearWeekType); int dayCount = weekCount * TimeSpec.DaysPerWeek; for (int i = 0; i < dayCount; i++) { days.Add(new Day(startDate.AddDays(i), Calendar)); } return(days); } // GetDays
} // Year // ---------------------------------------------------------------------- public ITimePeriodCollection GetDays() { TimePeriodCollection days = new TimePeriodCollection(); DateTime moment = Start.Date; while (moment <= End.Date) { days.Add(new Day(moment.Date, Calendar)); moment = moment.AddDays(1); } return(days); } // GetDays
} // GetDays // ---------------------------------------------------------------------- public ITimePeriodCollection GetWeeks() { TimePeriodCollection weeks = new TimePeriodCollection(); DateTime moment = Start.Date; while (moment < End.Date) { weeks.Add(new BroadcastWeek(moment.Date, Calendar)); moment = moment.AddDays(TimeSpec.DaysPerWeek); } return(weeks); } // GetWeeks
} // Halfyears // ---------------------------------------------------------------------- public ITimePeriodCollection GetHalfyears() { TimePeriodCollection halfyears = new TimePeriodCollection(); for (int i = 0; i < HalfyearCount; i++) { int year; YearHalfyear halfyear; TimeTool.AddHalfyear(BaseYear, StartHalfyear, i, out year, out halfyear); halfyears.Add(new Halfyear(year, halfyear, Calendar)); } return(halfyears); } // GetHalfyears
} // Months // ---------------------------------------------------------------------- public ITimePeriodCollection GetMonths() { TimePeriodCollection months = new TimePeriodCollection(); for (int i = 0; i < MonthCount; i++) { int year; YearMonth month; TimeTool.AddMonth(StartYear, StartMonth, i, out year, out month); months.Add(new Month(year, month, Calendar)); } return(months); } // GetMonths
} // Quarters // ---------------------------------------------------------------------- public ITimePeriodCollection GetQuarters() { TimePeriodCollection quarters = new TimePeriodCollection(); for (int i = 0; i < QuarterCount; i++) { int year; YearQuarter quarter; TimeTool.AddQuarter(BaseYear, StartQuarter, i, out year, out quarter); quarters.Add(new Quarter(year, quarter, Calendar)); } return(quarters); } // GetQuarters
} // HourCount // ---------------------------------------------------------------------- public ITimePeriodCollection GetMinutes() { TimePeriodCollection minutes = new TimePeriodCollection(); for (int hour = 0; hour < hourCount; hour++) { DateTime curHour = startHour.AddHours(hour); for (int minute = 0; minute < TimeSpec.MinutesPerHour; minute++) { minutes.Add(new Minute(curHour.AddMinutes(minute), Calendar)); } } return(minutes); } // GetMinutes
} // HasIntersectionPeriods // ---------------------------------------------------------------------- public virtual ITimePeriodCollection IntersectionPeriods(DateTime test) { TimePeriodCollection intersectionPeriods = new TimePeriodCollection(); foreach (ITimePeriod period in periods) { if (period.HasInside(test)) { intersectionPeriods.Add(period); } } return(intersectionPeriods); } // IntersectionPeriods
} // EndDayName // ---------------------------------------------------------------------- public ITimePeriodCollection GetHours() { TimePeriodCollection hours = new TimePeriodCollection(); DateTime startDate = startDay; for (int day = 0; day < dayCount; day++) { DateTime curDay = startDate.AddDays(day); for (int hour = 0; hour < TimeSpec.HoursPerDay; hour++) { hours.Add(new Hour(curDay.AddHours(hour), Calendar)); } } return(hours); } // GetHours
} // GetQuarters // ---------------------------------------------------------------------- public ITimePeriodCollection GetMonths() { TimePeriodCollection months = new TimePeriodCollection(); for (int i = 0; i < halfyearCount; i++) { for (int month = 0; month < TimeSpec.MonthsPerHalfyear; month++) { int year; YearMonth yearMonth; TimeTool.AddMonth(startYear, YearBaseMonth, (i * TimeSpec.MonthsPerHalfyear) + month, out year, out yearMonth); months.Add(new Month(year, yearMonth, Calendar)); } } return(months); } // GetMonths
} // GetHalfyears // ---------------------------------------------------------------------- public ITimePeriodCollection GetQuarters() { TimePeriodCollection quarters = new TimePeriodCollection(); for (int i = 0; i < yearCount; i++) { for (int quarter = 0; quarter < TimeSpec.QuartersPerYear; quarter++) { int year; YearQuarter yearQuarter; TimeTool.AddQuarter(startYear, YearQuarter.First, (i * TimeSpec.QuartersPerYear) + quarter, out year, out yearQuarter); quarters.Add(new Quarter(year, yearQuarter, Calendar)); } } return(quarters); } // GetQuarters
} // EndMonthOfYearName // ---------------------------------------------------------------------- public ITimePeriodCollection GetDays() { TimePeriodCollection days = new TimePeriodCollection(); DateTime startDate = GetStartOfMonth(Calendar, startYear, startMonth); for (int month = 0; month < monthCount; month++) { DateTime monthStart = startDate.AddMonths(month); int daysOfMonth = TimeTool.GetDaysInMonth(monthStart.Year, monthStart.Month); for (int day = 0; day < daysOfMonth; day++) { days.Add(new Day(monthStart.AddDays(day), Calendar)); } } return(days); } // GetDays
} // EndYearName // ---------------------------------------------------------------------- public ITimePeriodCollection GetHalfyears() { TimePeriodCollection halfyears = new TimePeriodCollection(); for (int i = 0; i < yearCount; i++) { for (int halfyear = 0; halfyear < TimeSpec.HalfyearsPerYear; halfyear++) { int year; YearHalfyear yearHalfyear; TimeTool.AddHalfyear(startYear, YearHalfyear.First, (i * TimeSpec.HalfyearsPerYear) + halfyear, out year, out yearHalfyear); halfyears.Add(new Halfyear(year, yearHalfyear, Calendar)); } } return(halfyears); } // GetHalfyears
} // CombinePeriods // ---------------------------------------------------------------------- private static ITimePeriodCollection IntersectCombinedPeriods(ITimeLineMomentCollection timeLineMoments) { TimePeriodCollection periods = new TimePeriodCollection(); if (timeLineMoments.IsEmpty) { return(periods); } // search for periods int intersectionStart = -1; int balance = 0; for (int i = 0; i < timeLineMoments.Count; i++) { ITimeLineMoment moment = timeLineMoments[i]; int startCount = moment.StartCount; int endCount = moment.EndCount; balance += startCount; balance -= endCount; // intersection is starting by a period start if (startCount > 0 && balance > 1 && intersectionStart < 0) { intersectionStart = i; continue; } // intersection is starting by a period end if (endCount <= 0 || balance > 1 || intersectionStart < 0) { continue; } T period = new T(); period.Setup(timeLineMoments[intersectionStart].Moment, moment.Moment); periods.Add(period); intersectionStart = -1; } return(periods); } // IntersectCombinedPeriods
} // IntersectionPeriods // ---------------------------------------------------------------------- public virtual ITimePeriodCollection RelationPeriods(ITimePeriod test, PeriodRelation relation) { if (test == null) { throw new ArgumentNullException("test"); } TimePeriodCollection relationPeriods = new TimePeriodCollection(); foreach (ITimePeriod period in periods) { if (test.GetRelation(period) == relation) { relationPeriods.Add(period); } } return(relationPeriods); } // RelationPeriods
} // HasIntersectionPeriods // ---------------------------------------------------------------------- public virtual ITimePeriodCollection IntersectionPeriods(ITimePeriod test) { if (test == null) { throw new ArgumentNullException("test"); } TimePeriodCollection intersectionPeriods = new TimePeriodCollection(); foreach (ITimePeriod period in periods) { if (test.IntersectsWith(period)) { intersectionPeriods.Add(period); } } return(intersectionPeriods); } // IntersectionPeriods
} // HasOverlapPeriods // ---------------------------------------------------------------------- public virtual ITimePeriodCollection OverlapPeriods(ITimePeriod test) { if (test == null) { throw new ArgumentNullException("test"); } TimePeriodCollection overlapPeriods = new TimePeriodCollection(); foreach (ITimePeriod period in periods) { if (test.OverlapsWith(period)) { overlapPeriods.Add(period); } } return(overlapPeriods); } // OverlapPeriods
} // GetTimeLineMoments // ---------------------------------------------------------------------- private ITimeLineMomentCollection GetTimeLineMoments(ICollection <ITimePeriod> momentPeriods) { TimeLineMomentCollection timeLineMoments = new TimeLineMomentCollection(); if (momentPeriods.Count == 0) { return(timeLineMoments); } // setup gap set with all start/end points ITimePeriodCollection intersections = new TimePeriodCollection(); foreach (ITimePeriod momentPeriod in momentPeriods) { if (momentPeriod.IsMoment) { continue; } // calculate the intersection between the periods ITimeRange intersection = limits.GetIntersection(momentPeriod); if (intersection == null || intersection.IsMoment) { continue; } if (periodMapper != null) { intersection = new TimeRange(MapPeriodStart(intersection.Start), MapPeriodEnd(intersection.End)); } intersections.Add(intersection); } timeLineMoments.AddAll(intersections); return(timeLineMoments); } // GetTimeLineMoments
} // 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
} // IntersectCombinedPeriods // ---------------------------------------------------------------------- private static ITimePeriodCollection CalculateGaps(ITimePeriod range, ITimeLineMomentCollection timeLineMoments) { TimePeriodCollection gaps = new TimePeriodCollection(); if (timeLineMoments.IsEmpty) { return(gaps); } // range leading gap ITimeLineMoment periodStart = timeLineMoments.Min; if (periodStart != null && range.Start < periodStart.Moment) { T startingGap = new T(); startingGap.Setup(range.Start, periodStart.Moment); gaps.Add(startingGap); } // search for gaps int itemIndex = 0; while (itemIndex < timeLineMoments.Count) { ITimeLineMoment moment = timeLineMoments[itemIndex]; int startCount = moment.StartCount; if (startCount == 0) { throw new InvalidOperationException(); } // search next gap start // use balancing to handle overlapping periods int balance = startCount; ITimeLineMoment gapStart = null; while (itemIndex < timeLineMoments.Count - 1 && balance > 0) { itemIndex++; gapStart = timeLineMoments[itemIndex]; balance += gapStart.BalanceCount; } if (gapStart == null) { throw new InvalidOperationException(); } if (gapStart.StartCount > 0) // touching { itemIndex++; continue; } // found a gap if (itemIndex < timeLineMoments.Count - 1) { T gap = new T(); gap.Setup(gapStart.Moment, timeLineMoments[itemIndex + 1].Moment); gaps.Add(gap); } itemIndex++; } // range closing gap ITimeLineMoment periodEnd = timeLineMoments.Max; if (periodEnd != null && range.End > periodEnd.Moment) { T endingGap = new T(); endingGap.Setup(periodEnd.Moment, range.End); gaps.Add(endingGap); } return(gaps); } // CalculateGaps