/// <summary> /// Splits a reporting period into units-of-time by a specified granularity. /// </summary> /// <param name="reportingPeriod">The reporting period to split.</param> /// <param name="granularity">The granularity to use when splitting.</param> /// <param name="overflowStrategy"> /// The strategy to use when <paramref name="granularity"/> is less granular than /// the <paramref name="reportingPeriod"/> and, when splitting, the resulting units-of-time /// cannot be aligned with the start and end of the reporting period. For example, /// splitting Mar2015-Feb2017 by year results in 2015,2016,2017, however only 2016 is /// fully contained within the reporting period. The reporting period is missing Jan2015-Feb2015 /// and March2017-Dec2017. /// </param> /// <returns> /// Returns the units-of-time that split the specified reporting period by the specified granularity. /// The units-of-time will always be in the specified granularity, regardless of the granularity /// of the reporting period (e.g. splitting a fiscal month reporting period using yearly granularity /// will return <see cref="FiscalYear"/> objects). /// </returns> /// <exception cref="ArgumentNullException"><paramref name="reportingPeriod"/> is null.</exception> /// <exception cref="ArgumentException"><paramref name="reportingPeriod"/> has an <see cref="UnitOfTimeGranularity.Unbounded"/> component.</exception> /// <exception cref="ArgumentException"><paramref name="granularity"/> is <see cref="UnitOfTimeGranularity.Invalid"/>.</exception> /// <exception cref="ArgumentException"><paramref name="granularity"/> is <see cref="UnitOfTimeGranularity.Unbounded"/>.</exception> /// <exception cref="ArgumentException"><paramref name="overflowStrategy"/> is not <see cref="OverflowStrategy.ThrowOnOverflow"/>.</exception> /// <exception cref="InvalidOperationException">There was some overflow when splitting.</exception> public static IList <UnitOfTime> Split( this IReportingPeriod <UnitOfTime> reportingPeriod, UnitOfTimeGranularity granularity, OverflowStrategy overflowStrategy = OverflowStrategy.ThrowOnOverflow) { if (reportingPeriod == null) { throw new ArgumentNullException(nameof(reportingPeriod)); } if (reportingPeriod.HasComponentWithUnboundedGranularity()) { throw new ArgumentException(Invariant($"{nameof(reportingPeriod)} has an {nameof(UnitOfTimeGranularity.Unbounded)} component.")); } if (granularity == UnitOfTimeGranularity.Invalid) { throw new ArgumentException(Invariant($"{nameof(granularity)} is {nameof(UnitOfTimeGranularity.Invalid)}")); } if (granularity == UnitOfTimeGranularity.Unbounded) { throw new ArgumentException(Invariant($"{nameof(granularity)} is {nameof(UnitOfTimeGranularity.Unbounded)}")); } if (overflowStrategy != OverflowStrategy.ThrowOnOverflow) { throw new ArgumentException(Invariant($"{nameof(overflowStrategy)} is not {nameof(OverflowStrategy.ThrowOnOverflow)}")); } var reportingPeriodGranularity = reportingPeriod.GetUnitOfTimeGranularity(); IList <UnitOfTime> result; if (reportingPeriodGranularity == granularity) { result = reportingPeriod.GetUnitsWithin(); } else if (reportingPeriodGranularity.IsLessGranularThan(granularity)) { result = reportingPeriod.MakeMoreGranular(granularity).GetUnitsWithin(); } else { result = reportingPeriod.MakeLessGranular(granularity).GetUnitsWithin(); } return(result); }
public static ICollection <IReportingPeriod <T> > CreatePermutations <T>( this IReportingPeriod <T> reportingPeriod, int maxUnitsInAnyReportingPeriod) where T : UnitOfTime { if (reportingPeriod == null) { throw new ArgumentNullException(nameof(reportingPeriod)); } if (reportingPeriod.HasComponentWithUnboundedGranularity()) { throw new ArgumentException(Invariant($"{nameof(reportingPeriod)} has an {nameof(UnitOfTimeGranularity.Unbounded)} component.")); } if (maxUnitsInAnyReportingPeriod < 1) { throw new ArgumentOutOfRangeException(nameof(maxUnitsInAnyReportingPeriod), "max units in any reporting period is <= 0"); } var allUnits = reportingPeriod.GetUnitsWithin(); var allReportingPeriods = new List <IReportingPeriod <T> >(); for (int unitOfTimeIndex = 0; unitOfTimeIndex < allUnits.Count; unitOfTimeIndex++) { for (int numberOfUnits = 1; numberOfUnits <= maxUnitsInAnyReportingPeriod; numberOfUnits++) { if (unitOfTimeIndex + numberOfUnits - 1 < allUnits.Count) { var subReportingPeriod = new ReportingPeriod <T>(allUnits[unitOfTimeIndex], allUnits[unitOfTimeIndex + numberOfUnits - 1]); allReportingPeriods.Add(subReportingPeriod); } } } return(allReportingPeriods); }