Split a period of time into multiple time periods

c#

Solution

This is one that works and takes care of some edge cases also:

var realDates = splitDates
    .Where(d => d > dateFrom && d < dateTo)
    .Concat(new List<DateTime>() {dateFrom.AddDays(-1), dateTo})
    .Select(d => d.Date)
    .Distinct()
    .OrderBy(d => d)
    .ToList();

// now we have             (start - 1) -- split1 -- split2 -- split3 -- end
// we zip it against          split1   -- split2 -- split3 --  end
// and produce       start,split1 -- split1+1,split2 -- split2+1,split3 -- split3+1,end

realDates.Zip(realDates.Skip(1), (a, b) => Tuple.Create(a.AddDays(1), b));

Problem

If i have a time period, lets say `DateFrom` and `DateTo` and I have a list of Dates, These dates will be the split dates. For example: ``` DateTime dateFrom = new DateTime(2012, 1, 1); DateTime dateTo = new DateTime(2012, 12, 31); List<DateTime> splitDates = new List<DateTime> { new DateTime(2012,2,1), new DateTime(2012,5,1), new DateTime(2012,7,1), new DateTime(2012,11,1), }; List<Tuple<DateTime, DateTime>> periods = SplitDatePeriod(dateFrom, dateTo, splitDates); ``` I want the result to be a list of periods, so for the previous example the result should be: ``` (01/01/2012 - 01/02/2012) (02/02/2012 - 01/05/2012) (02/05/2012 - 01/07/2012) (02/07/2012 - 01/11/2012) (02/11/2012 - 31/12/2012) ``` I have already wrote a method to do that: ``` List<Tuple<DateTime, DateTime>> SplitDatePeriod(DateTime dateFrom, DateTime dateTo, List<DateTime> splitDates) { var resultDates = new List<Tuple<DateTime, DateTime>>(); // sort split dates List<DateTime> _splitDates = splitDates.OrderBy(d => d.Date).ToList(); DateTime _curDate = dateFrom.Date; for (int i = 0; i <= _splitDates.Count; ++i) { DateTime d = (i < _splitDates.Count) ? _splitDates[i] : dateTo; // skip dates out of range if (d.Date < dateFrom.Date || d.Date > dateTo.Date) continue; resultDates.Add(Tuple.Create(_curDate, d)); _curDate = d.AddDays(1); } return resultDates; } ``` The Question It looks so ugly, Is there more neat and shorter way of doing this? using Linq maybe?

Original source