Deterministic, testable, and replayable time for .NET
$ dotnet add package EonaCat.DeterministicTimeEonaCat.DeterministicTime is a .NET library for deterministic, testable, and replayable time.
It replaces DateTime.UtcNow, Stopwatch, Timer, and Task.Delay with deterministic equivalents and supports advanced features like:
scheduling, time scaling, replay, NTP offsets, ASP.NET Framework integration. ASP.NET Core integration.
dotnet add package EonaCat.DeterministicTime
dotnet add package DeterministicTime.AspNetCore
dotnet add package DeterministicTime.AspNetFramework
ASP.NET 4.8 → add DeterministicTime.AspNetFramework and register HttpModule in web.config:
<system.web>
<httpModules>
<add name="DeterministicTime" type="DeterministicTimeHttpModule"/>
</httpModules>
</system.web>
using DeterministicTime;
DateTime now = DeterministicTime.UtcNow;
DateTime localNow = DeterministicTime.Now;
using (TimeScope.Frozen(DateTime.Parse("2025-01-01T00:00:00Z")))
{
Console.WriteLine(DeterministicTime.UtcNow); // frozen
}
using (TimeScope.Scaled(10)) // 10x faster
{
// all timers and delays scale 10x
}
DeterministicTime.Advance(TimeSpan.FromHours(2));
using (TimeScope.Offset(TimeSpan.FromMinutes(5)))
{
// all UtcNow calls are offset by 5 minutes
}
var sw = DeterministicStopwatch.StartNew();
// do work
sw.Stop();
Console.WriteLine(sw.Elapsed);
int fired = 0;
DeterministicTimer.Start(TimeSpan.FromSeconds(10), () => fired++);
DeterministicTime.Advance(TimeSpan.FromSeconds(10));
Console.WriteLine(fired); // 1
bool completed = false;
await DeterministicDelay.For(TimeSpan.FromSeconds(5)).ContinueWith(_ => completed = true);
DeterministicTime.Advance(TimeSpan.FromSeconds(5));
Console.WriteLine(completed); // true
var scheduler = DeterministicScheduler.Global;
scheduler.Every(TimeSpan.FromMinutes(1), () => Console.WriteLine("Tick"));
DeterministicTime.Advance(TimeSpan.FromMinutes(5)); // fires 5 times
using var recording = TimeRecording.Start();
// run code
recording.Save("run.json");
using (TimeReplay.Load("run.json"))
{
// deterministic replay of UtcNow calls
}
using (NtpSynchronization.Sync(myNtpProvider))
{
// deterministic time aligned with NTP
}
IDistributedTimeCoordinator coordinator = ...;
DeterministicTime.Push(new DistributedTimeSource(coordinator));
Console.WriteLine(DeterministicTime.UtcNow);
app.UseDeterministicTime();
Each request runs in its own deterministic scope
Works with frozen/scaled time and timers
Deterministic UtcNow & Now
Stopwatch replacement
One-shot and repeated timers
Task.Delay replacement
Time scaling, freezing, offset
Scheduler for background jobs
Recording & replay for testing
NTP synchronization & distributed clocks
ASP.NET Core integration