private static void AppendWindowsBetween(DateTime start, DateTime end, DateTimeRange[] ranges, int rangeIndex, ICollection <DateTimeWindow> result) { if (start >= end || rangeIndex >= ranges.Length) { return; } var currentRange = ranges[rangeIndex]; var window = DateTimeWindow.Find(start, currentRange); if (window.Start < start) { if (window.Start + currentRange <= end) { window += currentRange; // Append buckets with a smaller range that are required before this one AppendWindowsBetween(start, window.Start.Value, ranges, rangeIndex + 1, result); } else { // This bucket is too large to fit in the interval, try with a smaller range AppendWindowsBetween(start, end, ranges, rangeIndex + 1, result); return; } } // Append buckets of this size until no more fit var windowEnd = window.Start + currentRange; while (windowEnd <= end) { result.Add(window); window += currentRange; windowEnd = windowEnd + currentRange; } if (window.Start < end) { // Append smaller buckets to fill the gap between bucket.Timestamp and end AppendWindowsBetween(window.Start.Value, end, ranges, rangeIndex + 1, result); } }
public static IReadOnlyCollection <DateTimeWindow> GetWindowsBetween(DateTime start, DateTime end, IReadOnlyCollection <DateTimeRange> granularities, EdgeMode edges = EdgeMode.Shrink) { var result = new List <DateTimeWindow>(); if (start >= end || granularities.Count == 0) { return(result); } var ranges = granularities.OrderByDescending(g => g).ToArray(); AppendWindowsBetween(start, end, ranges, 0, result); // In 'Grow' mode, ensure the returned list of buckets **at least** covers the start and end times if (edges == EdgeMode.Grow) { var smallestRange = ranges.Last(); if (result.Count == 0 || result[0].start > start) { // No buckets fit, or start bucket starts too late. // Add the smallest bucket starting before the start time var startWindow = DateTimeWindow.Find(start, smallestRange); result.Insert(0, startWindow); } var lastWindow = result.Last(); if (lastWindow.end < end) { // End bucket finishes too early. // Add the smallest bucket starting before the end time var finalWindow = DateTimeWindow.Find(end, smallestRange); result.Add(finalWindow); } } return(result.AsReadOnly()); }