Extension method to retrieve list of days in the current week I want to get all days of the current week (from Monday to Sunday) with a custom time. To do this, I have written an extension method for TimeSpan:

public static DateTime[] Daily(this TimeSpan ts)
{
    var days = DayOfWeek.Monday - DateTime.UtcNow.DayOfWeek;
    var startDate = DateTime.UtcNow.AddDays(days);
    List&lt;DateTime&gt; dates = new List&lt;DateTime&gt;();

    for(var i = 0; i &lt; 7; i++)
    {
        dates.Add(startDate.Date + ts);
        startDate = startDate.AddDays(1);
    }

    return dates.ToArray();
}


As an example of how it would be used, new TimeSpan(17, 0, 0).Daily() will return:


23/01/2016 17:00:00 
24/01/2016 17:00:00
25/01/2016 17:00:00
26/01/2016 17:00:00
27/01/2016 17:00:00
28/01/2016 17:00:00
29/01/2016 17:00:00


Any suggestions on ways to improve my code?
Let's talk about two major things in this: building a modular API, and Unit Testing.

This can be easily unit tested, you should have 7 tests, one for a date in each day of the week. Let's pick a Week (past, present or future, doesn't matter), for this I'm going to pick an easy week. Since DayOfWeek.Monday is the first day of your week, we'll pick the first week of a month that starts on a Monday.

Scrolling backwards in my calendar I found August, 2016. August 1st, 2016 is a Monday, so we'll test that week.

The problem right now with your code is that it cannot be tested. You have to reset the system clock to test it. This is not a hard problem to fix. We'll redefine the API a little bit (add a default parameter, basically):

public static DateTime[] Daily(this TimeSpan ts, DateTime? checkDay = null)


So that's easy, now we can specify a specific day to check. All we have to do in the code is use that variable.

var weekDate = checkDay ?? DateTime.UtcNow;


Bam. That should be the first line of the method. That will make sure we get weekDate set to a valid DateTime.

Alright, good. So we redesigned the API a little and made it support an extra feature with no effort. Now we need to talk about that return.

Generally speaking: robust, modular API's that return a collection should return an IEnumerable&lt;T&gt; of some sort. I may have the user specify a specific DayOfWeek and try to find the first date in a give week that is that DayOfWeek, so I don't need the entire list (potentially). This is because each caller has different requirements (potentially), and to most closely follow SRP we shouldn't care about the resulting collection.

Our API doesn't need to worry about the collection as a whole, only generating each element in it. This may be a bizarre concept to understand at first, but our method should not care what the caller is going to do with the collection itself. We just generate it, so we don't need a list or array, we just need to return each element as it's generated.

We do this by returning an IEnumerable&lt;DateTime&gt; so that we can use the yield return statement instead of return. This will allow us to make a more modular API that doesn't always have to enumerate everything. It's the caller's responsibility to call .ToArray() if they need an array, or .ToList(), or enumerate it, ect.

public static IEnumerable&lt;DateTime&gt; Daily(this TimeSpan ts, DateTime? checkDay = null)


Lastly, different users' may have their week start on a different day. We want to accommodate for that, so we'll create a new default parameter for that.

public static IEnumerable&lt;DateTime&gt; Daily(this TimeSpan ts, DayOfWeek startDayOfWeek = DayOfWeek.Monday, DateTime? checkDay = null)


Bam. Now we've built a much more robust API that can be tested more easily as well. It should be trivial to implement this, in fact, we only need to change a few parts of your original code.

public static IEnumerable&lt;DateTime&gt; Daily(this TimeSpan ts, DayOfWeek startDayOfWeek = DayOfWeek.Monday, DateTime? checkDay = null)
{
    var compDate = checkDay ?? DateTime.UtcNow;
    var days = startDayOfWeek - compDate.DayOfWeek;
    var startDate = compDate.AddDays(days);

    for (var i = 0; i &lt; 7; i++)
    {
        yield return startDate.AddDays(i).Date + ts;
    }
}


It's even shorter now, supports your original use-case, and add's many more supported use-cases.

Then we build Unit-tests, they'll all have mostly the same body:

var expected = new DateTime[]
{
    new DateTime(2016, 8, 1, 15, 0, 0),
    new DateTime(2016, 8, 2, 15, 0, 0),
    new DateTime(2016, 8, 3, 15, 0, 0),
    new DateTime(2016, 8, 4, 15, 0, 0),
    new DateTime(2016, 8, 5, 15, 0, 0),
    new DateTime(2016, 8, 6, 15, 0, 0),
    new DateTime(2016, 8, 7, 15, 0, 0)
};
var inputTimeSpan = new TimeSpan(15, 0, 0);
var inputDate = new DateTime(2016, 8, 1);

var actual = Daily(inputTimeSpan, checkDay: inputDate).ToArray();

CollectionAssert.AreEquivalent(expected, actual);


Just change inputDate. Once we do this we'll see that on 2016-08-01 we get a failed result. No big deal, we just need to make sure we fix our method. (Easy fix too.)

Our bug is the offset, on Sunday you'll get Monday-Sunday for the upcoming week. (So on 7 Aug 2016 you get 8 Aug 2016 - 14 Aug 2016.) That's fine, to fix it we'll just check if days &gt; 0 and if so we'll subtract from it.

days = days &gt; 0 ? days - 7 : days;


We'll just add that after we assign days the first time, and bam. We're done.



Final Code

public static IEnumerable&lt;DateTime&gt; Daily(this TimeSpan ts, DayOfWeek startDayOfWeek = DayOfWeek.Monday, DateTime? checkDay = null)
{
    var compDate = checkDay ?? DateTime.UtcNow;
    var days = startDayOfWeek - compDate.DayOfWeek;
    days = days &gt; 0 ? days - 7 : days;
    var startDate = compDate.AddDays(days);

    for (var i = 0; i &lt; 7; i++)
    {
        yield return startDate.AddDays(i).Date + ts;
    }
}


As you can see, it's still nice and short, and it's more robust than the original. :) This was an excellent start, and hopefully you take more out of this than just a bug fix. :)