public class TimeRange {
public DateTime? Start { get; set; }
public DateTime? End { get; set; }
public static IEnumerable<T> Select<T> (params T[] args) => args;
// [---------------] [----------] <= children
// [---------------] <= children
// ==>
// [-------------------------] <= parent
// [-----][----][---][-------]
public static IEnumerable<TimeRange> GetPeriodsFlattened(ITimeRange parent, IEnumerable<ITimeRange> children)
{
if (!children.Any())
{
yield return new TimeRange(parent.Start, parent.End);
yield break;
}
var allTimesInParent = children.SelectMany(x => LinqHelper.Select(x.Start, x.End))
.Concat(LinqHelper.Select(parent.Start, parent.End))
.Where(x => x.HasValue && x >= parent.Start && x <= parent.End)
.OrderBy(x => x).Distinct().ToList();
if (allTimesInParent.Count < 2)
{
yield return new TimeRange(parent.Start, parent.End);
yield break;
}
DateTime? prev = null;
foreach (var curr in allTimesInParent)
{
if (prev != null)
yield return new TimeRange(prev, curr);
prev = curr;
}
}
}
void Main () {
var ranges = new List<TimeRange> () {
new TimeRange {
Start = null,
End = new DateTime (2020, 1, 15)
},
new TimeRange {
Start = new DateTime (2020, 1, 14),
End = new DateTime (2020, 1, 18)
},
new TimeRange {
Start = new DateTime (2020, 1, 20),
End = null
}
};
var parentRange = new TimeRange () {
Start = new DateTime (2020, 1, 12),
End = new DateTime (2020, 2, 28)
};
var flattened = TimeRange.GetPeriodsFlattened (parentRange, ranges);
foreach (var range in flattened) {
Console.WriteLine (range.Start.ToString () + " - " + range.End.ToString ());
}
}
/* CONSOLE OUTPUT:
12-1-2020 00:00:00 - 14-1-2020 00:00:00
14-1-2020 00:00:00 - 15-1-2020 00:00:00
15-1-2020 00:00:00 - 18-1-2020 00:00:00
18-1-2020 00:00:00 - 20-1-2020 00:00:00
20-1-2020 00:00:00 - 28-2-2020 00:00:00
*/
514200cookie-checkFlatten time periods