C DateTime.Now precision
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
DateTime.Now in C# has a resolution of approximately 10-15 milliseconds on most Windows systems, despite the DateTime struct storing values with 100-nanosecond precision (ticks). This means two consecutive calls to DateTime.Now can return the same value even if real time has passed. For high-precision timing, use Stopwatch or DateTime.UtcNow (which avoids timezone conversion overhead).
DateTime Resolution vs Precision
The DateTime struct can represent time down to 100-nanosecond intervals (ticks), but DateTime.Now does not update that frequently:
The system clock updates at intervals determined by the OS timer resolution — typically 15.625ms on Windows (64 Hz).
Key Terminology
| Term | Definition |
| Resolution | How often the clock updates (~15ms for DateTime.Now) |
| Precision | Smallest representable unit (100ns / 1 tick for DateTime) |
| Accuracy | How close the value is to the true time (depends on NTP sync) |
DateTime.Now has high precision (100ns ticks) but low resolution (15ms updates). It is like a ruler marked in millimeters but only read with a magnifying glass every centimeter.
Demonstrating the Resolution Limit
Only a handful of distinct values appear because the clock does not update between calls.
DateTime.Now vs DateTime.UtcNow
DateTime.Now converts from UTC to local time on every call, adding overhead:
DateTime.UtcNow is faster because it skips timezone conversion. Both have the same ~15ms resolution.
High-Precision Timing with Stopwatch
For measuring elapsed time with microsecond or nanosecond precision, use Stopwatch:
Stopwatch uses the hardware performance counter (QueryPerformanceCounter on Windows), which has nanosecond resolution.
Increasing System Timer Resolution
On Windows, you can increase the timer resolution to ~1ms using timeBeginPeriod:
Warning: Increasing timer resolution increases power consumption system-wide. Always restore the default when done.
.NET 8+ Improvements
Starting with .NET 8, TimeProvider offers a testable abstraction:
Generating Unique Timestamps
If you need monotonically increasing timestamps (e.g., for ordering events):
Or simply use a counter suffix or Guid.NewGuid() for uniqueness.
Common Pitfalls
- Using DateTime.Now for performance measurement:
DateTime.Nowhas 15ms resolution, making it useless for sub-millisecond benchmarks. UseStopwatchinstead. - Assuming unique timestamps: Two events within the same 15ms window get the same
DateTime.Nowvalue. Do not use timestamps as unique identifiers. - DateTime.Now in tight loops:
DateTime.Nowperforms a timezone conversion on every call. In hot loops, useDateTime.UtcNowand convert to local time once at display time. - Cross-platform differences: Linux and macOS have higher timer resolution (~1ms) than Windows (~15ms). Code that works on Linux may behave differently on Windows.
- Thread.Sleep precision:
Thread.Sleep(1)actually sleeps for ~15ms on Windows due to the same timer resolution. UseSpinWaitorStopwatchfor sub-millisecond delays.
Summary
DateTime.Nowhas ~15ms resolution on Windows despite storing 100ns ticks- Use
Stopwatchfor high-precision elapsed time measurement - Use
DateTime.UtcNowinstead ofDateTime.Nowfor better performance (no timezone conversion) - Do not rely on
DateTime.Nowfor unique timestamps or sub-millisecond accuracy - On .NET 8+, use
TimeProviderfor testable time abstractions

