Code4IT

The place for .NET enthusiasts, Azure lovers, and backend developers

C# Tip: injecting and testing the current time with TimeProvider and FakeTimeProvider

2025-09-02 4 min read CSharp Tips
Just a second! 🫷
If you are here, it means that you are a software developer. So, you know that storage, networking, and domain management have a cost .

If you want to support this blog, please ensure that you have disabled the adblocker for this site. I configured Google AdSense to show as few ADS as possible - I don't want to bother you with lots of ads, but I still need to add some to pay for the resources for my site.

Thank you for your understanding.
- Davide

Things that depend on concrete stuff are difficult to use when testing. Think of the file system: to have tests work properly, you have to ensure that the file system is structured exactly as you are expecting it to be.

A similar issue occurs with dates: if you create tests based on the current date, they will fail the next time you run them.

In short, you should find a way to abstract these functionalities, to make them usable in the tests.

In this article, we are going to focus on the handling of dates: we’ll learn what the TimeProvider class is, how to use it and how to mock it.

The old way for handling dates: a custom interface

Back in the days, the most straightforward approach to add abstraction around the date management was to manually create an interface, or an abstract class, to wrap the access to the current date:

public interface IDateTimeWrapper
{
    DateTime GetCurrentDate();
}

Then, the standard implementation implemented the interface by using only the UTC date:

public class DateTimeWrapper : IDateTimeWrapper
{
    public DateTime GetCurrentDate() => DateTime.UtcNow;
}

A similar approach is to have an abstract class instead:

public abstract class DateTimeWrapper
{
    public virtual DateTime GetCurrentDate() => DateTime.UctNow;
}

Easy: you then have to add an instance of it in the DI engine, and you are good to go.

The only problem? You have to do it for every project you are working on. Quite a waste of time!

How to use TimeProvider in a .NET application to get the current date

Along with .NET 8, the .NET team released an abstract class named TimeProvider. This abstract class, beyond providing an abstraction for local time, exposes methods for working with high-precision timestamps and TimeZones.

It’s important to notice that dates are returned as DateTimeOffset, and not as DateTime instances.

TimeProvider comes out-of-the-box with a .NET Console application, accessible as a singleton:

static void Main(string[] args)
{
    Console.WriteLine("Hello, World!");
   
    DateTimeOffset utc = TimeProvider.System.GetUtcNow();
    Console.WriteLine(utc);

    DateTimeOffset local = TimeProvider.System.GetLocalNow();
    Console.WriteLine(local);
}

On the contrary, if you need to use Dependency Injection, for example, in .NET APIs, you have to inject it as a singleton, like this:

builder.Services.AddSingleton(TimeProvider.System);

So that you can use it like this:

public class SummerVacationCalendar
{
    private readonly TimeProvider _timeProvider;

    public SummerVacationCalendar(TimeProvider timeProvider)
 {
        this._timeProvider = timeProvider;
 }

    public bool ItsVacationTime()
 {
        var today = _timeProvider.GetLocalNow();
        return today.Month == 8;
 }
}

How to test TimeProvider with FakeTimeProvider

Now, how can we test the ItsVacationTime of the SummerVacationCalendar class?

We can use the Microsoft.Extensions.TimeProvider.Testing NuGet library, still provided by Microsoft, which provides a FakeTimeProvider class that acts as a stub for the TimeProvider abstract class:

TimeProvider.Testing NuGet package

By using the FakeTimeProvider class, you can set the current UTC and Local time, as well as configure the other options provided by TimeProvider.

Here’s an example:

[Fact]
public void WhenItsAugust_ShouldReturnTrue()
{
 // Arrange
    var fakeTime = new FakeTimeProvider();
    fakeTime.SetUtcNow(new DateTimeOffset(2025, 8, 14, 22, 24, 12, TimeSpan.Zero));
    var sut = new SummerVacationCalendar(fakeTime);

 // Act
    var isVacation = sut.ItsVacationTime();

 // Assert
    Assert.True(isVacation);
}

[Fact]
public void WhenItsNotAugust_ShouldReturnFalse()
{
 // Arrange
    var fakeTime = new FakeTimeProvider();
    fakeTime.SetUtcNow(new DateTimeOffset(2025, 3, 14, 22, 24, 12, TimeSpan.Zero));
    var sut = new SummerVacationCalendar(fakeTime);

 // Act
    var isVacation = sut.ItsVacationTime();

 // Assert
    Assert.False(isVacation);
}

Further readings

Actually, TimeProvider provides way more functionalities than just returning the UTC and the Local time.

Maybe we’ll explore them in the future. But for now, do you know how the DateTimeKind enumeration impacts the way you create new DateTimes?

🔗 C# tip: create correct DateTimes with DateTimeKind | Code4IT

This article first appeared on Code4IT 🐧

However, always remember to test the code not against the actual time but against static values. But, if for some reason you cannot add TimeProvider in your classes, there are other less-intrusive strategies that you can use (and that can work for other types of dependencies as well, like the file system):

🔗 3 ways to inject DateTime and test it | Code4IT

Wrapping up

I hope you enjoyed this article! Let’s keep in touch on LinkedIn, Twitter or BlueSky! 🤜🤛

Happy coding!

🐧

About the author

Davide Bellone is a Principal Backend Developer with more than 10 years of professional experience with Microsoft platforms and frameworks.

He loves learning new things and sharing these learnings with others: that’s why he writes on this blog and is involved as speaker at tech conferences.

He's a Microsoft MVP 🏆, conference speaker (here's his Sessionize Profile) and content creator on LinkedIn.