Extract incomplete weeks from a DateTime collection The code below attempts to extract incomplete weeks from a List&lt;DateTime&gt;.

For example, a list containing all the days in Jan 2015 would result in the 5th to the 25th inclusive.

I know the list going in will contain unique dates, and are in date order. It seems to be working but I can't help but think this could be done better.

private IEnumerable&lt;DateTime&gt; extractIncompleteWeeks(IEnumerable&lt;DateTime&gt; dates)
{
    var mondays = dates
        .Where((d, i) =&gt; d.DayOfWeek == DayOfWeek.Monday)
        .Select(d =&gt; d.Date);

    var results = new List&lt;DateTime&gt;();

    foreach (var monday in mondays)
    {
        var fullWeek = new HashSet&lt;DateTime&gt;(dates.SkipWhile(d =&gt; d &lt; monday).Take(7).Select(d =&gt; d.Date));

        if (fullWeek.Last().Date == monday.AddDays(6).Date)
            results.AddRange(fullWeek);
    }

    return results;
}
Naming:

Names of methods in C# use PascalCasing. Your method name would become ExtractIncompleteWeeks. Although the naming convention is now correct, the name is ambiguous. Extract incomplete weeks means you want to fetch only the dates of the weeks which are incomplete. Instead rename it to ChopIncompleteWeeks or ExtractCompleteWeeks. This makes clear that you want to eliminate the incomplete weeks or want to extract the complete weeks.

Return type:

The return type of the method is an IEnumerable&lt;DateTime&gt; yet you return a List&lt;DateTime&gt;. Either make the return type also List&lt;DateTime&gt; but preferably return one element at a time by using yield.

private IEnumerable&lt;DateTime&gt; ExtractCompleteWeeks(IEnumerable&lt;DateTime&gt; dates)
{
    ...

    foreach (var monday in mondays)
    {
        ...

        if (fullWeek.Last().Date == monday.AddDays(6).Date)
        {
            foreach(var day in fullWeek)
            {
                yield return day;
            }
        }
    }
}


Here are some questions from StackOverflow and Programmers.SE regarding yield:


Proper Use of yield return
A practical use of “yield” keyword in C#


I really like this answer from the first question to get a very basic understanding of using yield instead of a temporary list:


  Populating a temporary list is like downloading the whole video, whereas using yield is like streaming that video.


HashSet:

Is there a specific reason why you create a HashSet&lt;DateTime&gt; only to take the last element and compare it against monday.AddDays(6).Date? You can replace that line by following:

var fullWeek = dates.SkipWhile(d =&gt; d &lt; monday).Take(7).Select(d =&gt; d.Date);


Complete code:

private IEnumerable&lt;DateTime&gt; ExtractCompleteWeeks(IEnumerable&lt;DateTime&gt; dates)
{
    var mondays = dates.Where(d =&gt; d.DayOfWeek == DayOfWeek.Monday)
                       .Select(d =&gt; d.Date);

    foreach (var monday in mondays)
    {
        var fullWeek = dates.SkipWhile(d =&gt; d &lt; monday).Take(7).Select(d =&gt; d.Date);

        if (fullWeek.Last().Date == monday.AddDays(6).Date)
        {
            foreach(var day in fullWeek)
            {
                yield return day;
            }
        }
    }
}