user336278
user336278

Reputation: 61

C# calculate date ranges from a list of dates

Given a list of dates (which may not be sorted), I want to build a list of date ranges -

E.g. Assuming MM/DD format,

Input - 5/1, 5/5, 5/6, 5/15, 5/7, 5/8, 5/19,5/20, 5/23

Output -

Date Range 1: 5/1 to 5/1
Date Range 2: 5/5 to 5/8
Date Range 3: 5/15 to 5/15
Date Range 4: 5/19 to 5/20
Date Range 5: 5/23 to 5/23

Basically, a range should be continuous.

Upvotes: 1

Views: 1752

Answers (3)

Jon-YYC
Jon-YYC

Reputation: 187

public class DateRange
{
    public DateTime Start { get; set; }
    public DateTime End { get; set; }
}

[TestClass]
public class DateRangerTest
{

    private List<DateRange> GetDateRanges(List<DateTime> dates)
    {
        if (dates == null || !dates.Any()) return null;
        dates = dates.OrderBy(x => x.Date).ToList();

        var dateRangeList = new List<DateRange>();

        DateRange dateRange = null;
        for (var i = 0; i < dates.Count; i++)
        {
            if (dateRange == null)
            {
                dateRange = new DateRange { Start = dates[i] };
            }
            if (i == dates.Count - 1 || dates[i].Date.AddDays(1) != dates[i + 1].Date)
            {
                dateRange.End = dates[i].Date;
                dateRangeList.Add(dateRange);
                dateRange = null;
            }
        }
        return dateRangeList;
    }

    [TestMethod]
    public void GetDateRanges_MultiDateRangeTest()
    {
        var dates = new List<DateTime>
        {
            new DateTime(1999,5,1),
            new DateTime(1999,5,5),
            new DateTime(1999,5,6),
            new DateTime(1999,5,15),
            new DateTime(1999,5,7),
            new DateTime(1999,5,8),
            new DateTime(1999,5,19),
            new DateTime(1999,5,20),
            new DateTime(1999,5,23)
        };

        var dateRanges = GetDateRanges(dates);

        Assert.AreEqual(new DateTime(1999, 5, 1), dateRanges[0].Start);
        Assert.AreEqual(new DateTime(1999, 5, 1), dateRanges[0].End);

        Assert.AreEqual(new DateTime(1999, 5, 5), dateRanges[1].Start);
        Assert.AreEqual(new DateTime(1999, 5, 8), dateRanges[1].End);

        Assert.AreEqual(new DateTime(1999, 5, 15), dateRanges[2].Start);
        Assert.AreEqual(new DateTime(1999, 5, 15), dateRanges[2].End);

        Assert.AreEqual(new DateTime(1999, 5, 19), dateRanges[3].Start);
        Assert.AreEqual(new DateTime(1999, 5, 20), dateRanges[3].End);

        Assert.AreEqual(new DateTime(1999, 5, 23), dateRanges[4].Start);
        Assert.AreEqual(new DateTime(1999, 5, 23), dateRanges[4].End);
    }
}

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1500145

  1. Sort the dates
  2. Start a range containing the next date (to start with it will be the first one)
  3. Is the second "valid" date the next date which would be in the range? If so, keep going. If not, close the current range and start a new one.
  4. Repeat until you've run out of dates, at which point you close the current range and you're done.

Upvotes: 5

Oded
Oded

Reputation: 498972

You can create a list of DateTime (possibly using the same year for them all) and sort it.

It is then fairly easy to find if a day and the next day exist in the list (using DateTime.AddDays(1)).

Upvotes: 0

Related Questions