Kuba's space

Kuba's space

Abstract current time using function in C#

I've seen many ways to deal with date and time. Hiding it behind an interface, a static class with a single property, ambient context, you name it. I never liked any of them.

Then the enlightenment came. In one of the projects, I've seen a function used to get the current time.
I've never thought of that! It doesn't need much code to put into use and is simple to test.
Take a look at an example.

First, you create a function for getting the current time and then pass it to the DateRangeCalculator.

public void ConfigureServices(IServiceCollection services)
{
    Func<DateTime> getCurrentTime = () => DateTime.Now;
    services.AddSingleton(_ => new DateRangeCalculator(getCurrentTime));
}

Our calculator implementation can look like this:

public class DateRangeCalculator {
    readonly Func<DateTime> _getCurrentTime;

    public DateRangeCalculator(Func<DateTime> getCurrentTime) =>
       _getCurrentTime = getCurrentTime;

    public DateTime GetLastMonth()
    {
        var currentTime = _getCurrentTime();
        var previousMonth = currentTime.Date.AddMonths(-1);

        return previousMonth;
    }
}

If you prefer a more functional approach, change GetLastMonth method to static and drop the constructor. I will leave it to you as an exercise.

How to test a class with such dependency?
Just replace the implementation in the test like so:

[Fact]
public void PreviousMonthRangeCalculator()
{
    Func<DateTime> currentTime = () => new DateTime(2021, 1,1);

    var result = DateRangeCalculator.GetLastMonth(currentTime);

    result.Month.Should().Be(12);
}

I like this idea because it doesn't require an interface with one method.
When it comes to tests, there is no need to create a mock class.
Less boilerplate, more readable code, what more do you need?

 
Share this