// ---------------------------------------------------------------------- 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 FiscalYearsNearestDayGetQuartersTest() { const int yearCount = 13; Years years = new Years(2006, yearCount, GetFiscalYearCalendar(FiscalYearAlignment.NearestDay)); ITimePeriodCollection quarters = years.GetQuarters(); Assert.AreNotEqual(quarters, null); Assert.AreEqual(quarters.Count, yearCount * TimeSpec.QuartersPerYear); Assert.AreEqual(quarters[0].Start, new DateTime(2006, 9, 3)); foreach (Quarter quarter in quarters) { // last quarter of a leap year // http://en.wikipedia.org/wiki/4-4-5_Calendar if ((quarter.YearQuarter == YearQuarter.Fourth) && (quarter.Year == 2011 || quarter.Year == 2016)) { Assert.AreEqual(quarter.Duration.Subtract(TimeCalendar.DefaultEndOffset).Days, TimeSpec.FiscalDaysPerLeapQuarter); } else { Assert.AreEqual(quarter.Duration.Subtract(TimeCalendar.DefaultEndOffset).Days, TimeSpec.FiscalDaysPerQuarter); } } } // FiscalYearsNearestDayGetQuartersTest
public void GetQuartersTest() { const int startYear = 2004; const int yearCount = 10; const YearMonth startMonth = YearMonth.October; const YearQuarter startQuarter = YearQuarter.Third; Years years = new Years(startYear, yearCount, TimeCalendar.New(startMonth)); ITimePeriodCollection quarters = years.GetQuarters(); Assert.AreNotEqual(quarters, null); int index = 0; foreach (Quarter quarter in quarters) { int quarterYear = startYear + ((index + (int)startQuarter) / TimeSpec.QuartersPerYear); Assert.AreEqual(quarter.Year, quarterYear); Assert.AreEqual(quarter.Start, years.Start.AddMonths(index * TimeSpec.MonthsPerQuarter)); Assert.AreEqual(quarter.End, quarter.Calendar.MapEnd(quarter.Start.AddMonths(TimeSpec.MonthsPerQuarter))); index++; } Assert.AreEqual(index, yearCount * TimeSpec.QuartersPerYear); } // GetQuartersTest
} // StartPeriodVisit // ---------------------------------------------------------------------- protected void StartPeriodVisit(ITimePeriod period, TContext context = null) { if (period == null) { throw new ArgumentNullException("period"); } if (period.IsMoment) { return; } OnVisitStart(); Years years = calendar != null ? new Years(period.Start.Year, period.End.Year - period.Start.Year + 1, calendar) : new Years(period.Start.Year, period.End.Year - period.Start.Year + 1); if (OnVisitYears(years, context) && EnterYears(years, context)) { ITimePeriodCollection yearsToVisit = years.GetYears(); if (seekDirection == SeekDirection.Backward) { yearsToVisit.SortByEnd(); } foreach (Year year in yearsToVisit) { if (!year.OverlapsWith(period) || OnVisitYear(year, context) == false) { continue; } // months if (EnterMonths(year, context) == false) { continue; } ITimePeriodCollection monthsToVisit = year.GetMonths(); if (seekDirection == SeekDirection.Backward) { monthsToVisit.SortByEnd(); } foreach (Month month in monthsToVisit) { if (!month.OverlapsWith(period) || OnVisitMonth(month, context) == false) { continue; } // days if (EnterDays(month, context) == false) { continue; } ITimePeriodCollection daysToVisit = month.GetDays(); if (seekDirection == SeekDirection.Backward) { daysToVisit.SortByEnd(); } foreach (Day day in daysToVisit) { if (!day.OverlapsWith(period) || OnVisitDay(day, context) == false) { continue; } // hours if (EnterHours(day, context) == false) { continue; } ITimePeriodCollection hoursToVisit = day.GetHours(); if (seekDirection == SeekDirection.Backward) { hoursToVisit.SortByEnd(); } foreach (Hour hour in hoursToVisit) { if (!hour.OverlapsWith(period) || OnVisitHour(hour, context) == false) { // ReSharper disable RedundantJumpStatement continue; // ReSharper restore RedundantJumpStatement } } } } } } OnVisitEnd(); } // StartPeriodVisit
public void FiscalYearTest() { DateTime testDate = new DateTime(2008, 11, 18); Year year = new Year(testDate, TimeCalendar.New(YearMonth.October)); Assert.Equal(YearMonth.October, year.YearBaseMonth); Assert.Equal(2008, year.BaseYear); // start & end Assert.Equal(year.Start.Year, testDate.Year); Assert.Equal(10, year.Start.Month); Assert.Equal(1, year.Start.Day); Assert.Equal(year.End.Year, testDate.Year + 1); Assert.Equal(9, year.End.Month); Assert.Equal(30, year.End.Day); // half years ITimePeriodCollection halfyears = year.GetHalfyears(); foreach (Halfyear halfyear in halfyears) { switch (halfyear.YearHalfyear) { case YearHalfyear.First: Assert.Equal(halfyear.Start, year.Start); Assert.Equal(halfyear.Start.Year, testDate.Year); Assert.Equal(10, halfyear.Start.Month); Assert.Equal(1, halfyear.Start.Day); Assert.Equal(halfyear.End.Year, testDate.Year + 1); Assert.Equal(3, halfyear.End.Month); Assert.Equal(31, halfyear.End.Day); break; case YearHalfyear.Second: Assert.Equal(halfyear.End, year.End); Assert.Equal(halfyear.Start.Year, testDate.Year + 1); Assert.Equal(4, halfyear.Start.Month); Assert.Equal(1, halfyear.Start.Day); Assert.Equal(halfyear.End.Year, testDate.Year + 1); Assert.Equal(9, halfyear.End.Month); Assert.Equal(30, halfyear.End.Day); break; } } // half years ITimePeriodCollection quarters = year.GetQuarters(); foreach (Quarter quarter in quarters) { switch (quarter.YearQuarter) { case YearQuarter.First: Assert.Equal(quarter.Start, year.Start); Assert.Equal(quarter.Start.Year, testDate.Year); Assert.Equal(10, quarter.Start.Month); Assert.Equal(1, quarter.Start.Day); Assert.Equal(quarter.End.Year, testDate.Year); Assert.Equal(12, quarter.End.Month); Assert.Equal(31, quarter.End.Day); break; case YearQuarter.Second: Assert.Equal(quarter.Start.Year, testDate.Year + 1); Assert.Equal(1, quarter.Start.Month); Assert.Equal(1, quarter.Start.Day); Assert.Equal(quarter.End.Year, testDate.Year + 1); Assert.Equal(3, quarter.End.Month); Assert.Equal(31, quarter.End.Day); break; case YearQuarter.Third: Assert.Equal(quarter.Start.Year, testDate.Year + 1); Assert.Equal(4, quarter.Start.Month); Assert.Equal(1, quarter.Start.Day); Assert.Equal(quarter.End.Year, testDate.Year + 1); Assert.Equal(6, quarter.End.Month); Assert.Equal(30, quarter.End.Day); break; case YearQuarter.Fourth: Assert.Equal(quarter.End, year.End); Assert.Equal(quarter.Start.Year, testDate.Year + 1); Assert.Equal(7, quarter.Start.Month); Assert.Equal(1, quarter.Start.Day); Assert.Equal(quarter.End.Year, testDate.Year + 1); Assert.Equal(9, quarter.End.Month); Assert.Equal(30, quarter.End.Day); break; } } // months ITimePeriodCollection months = year.GetMonths(); int monthIndex = 0; foreach (Month month in months) { switch (monthIndex) { case 0: Assert.Equal(month.Start, year.Start); break; case TimeSpec.MonthsPerYear - 1: Assert.Equal(month.End, year.End); break; } DateTime startDate = new DateTime(year.BaseYear, year.Start.Month, 1).AddMonths(monthIndex); Assert.Equal(month.Start.Year, startDate.Year); Assert.Equal(month.Start.Month, startDate.Month); Assert.Equal(month.Start.Day, startDate.Day); Assert.Equal(month.End.Year, startDate.Year); Assert.Equal(month.End.Month, startDate.Month); monthIndex++; } } // FiscalYearTest
/// <summary> /// De-tangles a list of overlapping Verbrauch entries where entries can be subsets of other entries. /// </summary> /// <example> /// [---v1---) /// [-----v2------) /// [---------v3---------) /// is transformed into /// [--v1---) /// ........[-v2--) /// ..............[--v3--) /// </example> /// <param name="input"></param> /// <returns></returns> public static List <Verbrauch> Detangle(IEnumerable <Verbrauch> input) { //var filteredInput = KeepShortestSlices(input); HashSet <Verbrauch> resultSet = new HashSet <Verbrauch>(); var groups = input.OrderBy(v => (v.Startdatum, v.Wertermittlungsverfahren, v.Obiskennzahl, v.Einheit)).GroupBy(v => new Tuple <Wertermittlungsverfahren, string, Mengeneinheit> ( v.Wertermittlungsverfahren, v.Obiskennzahl, v.Einheit )); foreach (var vGroup in groups) { HashSet <Verbrauch> subResult = new HashSet <Verbrauch>(); // find pairs (x,y) where x.end == y.start: // |----x----|--------y--------| //var adjacentVerbrauchs = from x in vGroup join y in vGroup on x.enddatum equals y.startdatum select new { x, y }; var adjacentVerbrauchs = from x in vGroup join y in vGroup on x.Enddatum equals y.Startdatum select new { x, y }; foreach (var av in adjacentVerbrauchs) { subResult.Add(av.x); subResult.Add(av.y); } // |----x----|--------y--------| // |-------------z-------------| // ==> delete z from result where z.start == x.start and z.end == y.end //var fullyRedundantVerbrauchs = from av in adjacentVerbrauchs join z in vGroup on new { av.x.startdatum, av.y.enddatum } equals new { z.startdatum, z.enddatum } select new { av, z }; var fullyRedundantVerbrauchs = from av in adjacentVerbrauchs join z in vGroup on new { av.x.Startdatum, av.y.Enddatum } equals new { z.Startdatum, z.Enddatum } select new { av, z }; foreach (var frv in fullyRedundantVerbrauchs) { if (frv.av.x.Wert + frv.av.y.Wert != frv.z.Wert) { throw new ArgumentException($"Inconsistent data detected: {JsonConvert.SerializeObject(frv.av.x)} + {JsonConvert.SerializeObject(frv.av.y)} ≠ {JsonConvert.SerializeObject(frv.z)}"); } subResult.Remove(frv.z); } // |----------x----------|---y---| // |---------------z-------------| // or // |---y---|----------x----------| // |---------------z-------------| // or // |---x1--|-----y------|---x2---| // |--------------z--------------| // y and z are given. find x such that x.value == y.value+z.value //subResult.UnionWith(vGroup); subResult.UnionWith(vGroup); foreach (Verbrauch z in new HashSet <Verbrauch>(subResult)) { var ys = subResult.Where(y => z.Contains(y) && !z.Equals(y)); if (ys.Count() > 0) { TimePeriodSubtractor <TimeRange> tps = new TimePeriodSubtractor <TimeRange>(); TimePeriodCollection source = new TimePeriodCollection { z.GetTimeRange() }; TimePeriodCollection subtract = new TimePeriodCollection(); subtract.AddAll(ys.Select(y => y.GetTimeRange())); ITimePeriodCollection subtractionResult = tps.SubtractPeriods(source, subtract); var xs = new HashSet <Verbrauch>(); foreach (var tr in subtractionResult) { Verbrauch v = new Verbrauch() { Einheit = z.Einheit, Wertermittlungsverfahren = z.Wertermittlungsverfahren, Obiskennzahl = z.Obiskennzahl, Startdatum = tr.Start, Enddatum = tr.End }; xs.Add(v); } var totalXWert = z.Wert - ys.Select(y => y.Wert).Sum(); var totalXDuration = xs.Select(x => x.GetDuration().TotalSeconds).Sum(); foreach (var x in xs) { x.Wert = (totalXWert * (decimal)x.GetDuration().TotalSeconds) / ((decimal)totalXDuration); } subResult.Remove(z); subResult.UnionWith(xs); } } resultSet.UnionWith(subResult); } List <Verbrauch> result = new List <Verbrauch>(resultSet); result.Sort(new VerbrauchDateTimeComparer()); return(result); }
} // PeriodMapper // ---------------------------------------------------------------------- public virtual ITimePeriodCollection SubtractPeriods(ITimePeriodContainer sourcePeriods, ITimePeriodCollection subtractingPeriods, bool combinePeriods = true) { if (sourcePeriods == null) { throw new ArgumentNullException("sourcePeriods"); } if (subtractingPeriods == null) { throw new ArgumentNullException("subtractingPeriods"); } if (sourcePeriods.Count == 0) { return(new TimePeriodCollection()); } if (subtractingPeriods.Count == 0 && !combinePeriods) { return(new TimePeriodCollection(sourcePeriods)); } // combined source periods sourcePeriods = timePeriodCombiner.CombinePeriods(sourcePeriods); // combined subtracting periods if (subtractingPeriods.Count == 0) { return(new TimePeriodCollection(sourcePeriods)); } subtractingPeriods = timePeriodCombiner.CombinePeriods(subtractingPeriods); // invert subtracting periods sourcePeriods.AddAll(timeGapCalculator.GetGaps(subtractingPeriods, new TimeRange(sourcePeriods.Start, sourcePeriods.End))); return(timePeriodIntersector.IntersectPeriods(sourcePeriods, combinePeriods)); } // SubtractPeriods
private ITimePeriodCollection CombinePeriods(ITimePeriodCollection periods) { var periodCombiner = new TimePeriodCombiner <TimeRange>(); return(periodCombiner.CombinePeriods(periods)); }
// ---------------------------------------------------------------------- public double NetworkDays( DateTime start, DateTime end, IEnumerable<DateTime> holidays = null, ITimePeriodCollection holidayPeriods = null ) { Day startDay = new Day( start < end ? start : end ); Day endDay = new Day( end > start ? end : start ); if ( startDay.Equals( endDay ) ) { return 0; } CalendarPeriodCollectorFilter filter = new CalendarPeriodCollectorFilter(); filter.AddWorkingWeekDays(); // only working days if ( holidays != null ) { foreach ( DateTime holiday in holidays ) { filter.ExcludePeriods.Add( new Day( holiday ) ); } } if ( holidayPeriods != null ) { filter.ExcludePeriods.AddAll( holidayPeriods ); } CalendarTimeRange testPeriod = new CalendarTimeRange( start, end ); CalendarPeriodCollector collector = new CalendarPeriodCollector( filter, testPeriod ); collector.CollectDays(); double networkDays = 0.0; foreach ( ICalendarTimeRange period in collector.Periods ) { networkDays += Math.Round( period.Duration.TotalDays, 2 ); } return networkDays; }
// ---------------------------------------------------------------------- public TimeSpan CalcWorkingPeriod( DateTime start, DateTime end, ITimePeriodCollection excludePeriods = null) { if ( start.Equals( end ) ) { return TimeSpan.Zero; } // test range TimeRange testRange = new TimeRange( start, end ); // search range DateTime searchStart = new Day( testRange.Start ).Start; DateTime serachEnd = new Day( testRange.End ).GetNextDay().Start; TimeRange searchPeriod = new TimeRange( searchStart, serachEnd ); // search filter CalendarPeriodCollectorFilter filter = new CalendarPeriodCollectorFilter(); filter.AddWorkingWeekDays(); // working days if ( excludePeriods != null ) { filter.ExcludePeriods.AddAll( excludePeriods ); } filter.CollectingHours.Add( new HourRange( 07, 12 ) ); // working hours filter.CollectingHours.Add( new HourRange( 13, 19 ) ); // working hours // collect working hours TimeCalendar calendar = new TimeCalendar( new TimeCalendarConfig { EndOffset = TimeSpan.Zero } ); CalendarPeriodCollector collector = new CalendarPeriodCollector( filter, searchPeriod, SeekDirection.Forward, calendar ); collector.CollectHours(); TimeSpan workingPeriod = new TimeSpan(); foreach ( ICalendarTimeRange period in collector.Periods ) { // get the intersection of the test-range and the day working-hours ITimePeriod intersection = testRange.GetIntersection( period ); if ( intersection == null ) { continue; } workingPeriod = workingPeriod.Add( intersection.Duration ); } return workingPeriod; }
// ---------------------------------------------------------------------- public double CalculateBusinessHours( CalendarTimeRange testPeriod, ITimePeriodCollection holidays = null ) { CalendarPeriodCollectorFilter filter = new CalendarPeriodCollectorFilter(); filter.CollectingMonths.Add( new MonthRange( YearMonth.January, YearMonth.January ) ); filter.CollectingDays.Add( new DayRange( 1, 1 ) ); filter.AddWorkingWeekDays(); // only working days filter.CollectingHours.Add( new HourRange( 8, 12 ) ); // opening hours morning filter.CollectingHours.Add( new HourRange( 13, 18 ) ); // opening hours afternoon if ( holidays != null ) { filter.ExcludePeriods.AddAll( holidays ); } CalendarPeriodCollector collector = new CalendarPeriodCollector( filter, testPeriod ); collector.CollectHours(); double businessHours = 0.0; foreach ( ICalendarTimeRange period in collector.Periods ) { businessHours += Math.Round( period.Duration.TotalHours, 2 ); } return businessHours; }
// ---------------------------------------------------------------------- private ITimePeriod GetCommonIntersection( ITimePeriodCollection periods ) { if ( periods.Count == 0 ) { return null; } ITimeRange timeRange = new TimeRange( periods[ 0 ] ); if ( periods.Count > 1 ) { for ( int i = 1; i < periods.Count; i++ ) { timeRange = timeRange.GetIntersection( periods[ i ] ); if ( timeRange == null ) { return null; } } } return timeRange; }