Another Time Machine

Another Time Machine

Introduction

In a previous article / blog post (I can never decide between the two terms), I wrote about creating a Time Provider by implementing an interface and injecting it into classes rather than hardcoding DateTime.Now.

However, there are more feature rich options available that are built into the Dot Net Framework, like the Microsoft.Bcl.TimeProvider in C#. It provides a systematic way to handle time in your applications, making code more testable and reliable. This article (or post) delves into how Microsoft.Bcl.TimeProvider can be used effectively in C#.

What is Microsoft.Bcl.TimeProvider?

Microsoft.Bcl.TimeProvider is part of the Microsoft BCL (Base Class Library) packages, providing an abstraction over the system clock. It allows developers to replace the direct use of DateTime.Now with a more flexible approach. This is particularly useful in unit testing scenarios where you need to control or mock the current time.

The TimeProvider abstracts the system time, allowing you to:

  • Replace DateTime.Now with a mockable interface.
  • Write unit tests that simulate any time or date, regardless of the actual system time.
  • Improve the reliability of time-dependent code.

Using Microsoft.Bcl.TimeProvider

Installation: First, install the package via NuGet Package Manager or using the Package Manager Console:

Install-Package Microsoft.Bcl.TimeProvider

Implementation in Code: Replace direct calls to DateTime.Now with TimeProvider.Current.UtcNow (or Now).

public class OrderProcessor 

    public void ProcessOrder(Order order)

        if (order.ExpiryDate < TimeProvider.Current.UtcNow) 

            // process expired order 
        } 
    } 
}

Mocking Time in Unit Tests: In your unit tests, set TimeProvider.Current to a mock or stub that returns a specific time.

[Test
public void ProcessOrder_ExpiredOrder_ShouldProcess() 
{ 
    TimeProvider.Currentnew StubTimeProvider 
    { 
        UtcNownewDateTime(20210101) 
    }; 
    
    var processornew OrderProcessor(); 
    var ordernew Order 
                      { 
                          ExpiryDatenew DateTime(20201231) 
                      }; 
    processor.ProcessOrder(order); 
    
    // Assert that order is processed 
}

Remember to reset TimeProvider.Current after your tests to avoid side effects.

Conclusion

The Microsoft.Bcl.TimeProvider is a valuable tool for C# developers dealing with time-sensitive logic.

By abstracting the system time, it facilitates more testable, maintainable, and reliable code. As with any abstraction, it should be used judiciously and in the right contexts to maximize its benefits.

Integrating this tool into your development practices can significantly improve the quality of your time-dependent functions.

Stephen

Hi, my name is Stephen Finchett. I have been a software engineer for over 30 years and worked on complex, business critical, multi-user systems for all of my career. For the last 15 years, I have been concentrating on web based solutions using the Microsoft Stack including ASP.Net, C#, TypeScript, SQL Server and running everything at scale within Kubernetes.