Summary
NetEvolve.Arguments provides ArgumentOutOfRangeException.ThrowIfInPast/ThrowIfInFuture overloads for DateTime, DateTimeOffset, and DateOnly (available on .NET 8+ target frameworks), optionally accepting a TimeProvider. NetEvolve.Arguments.Analyser does not currently have a rule that detects the manual equivalent of these checks.
Problem
The "now" side of the comparison varies significantly between codebases and has no single canonical form, e.g.:
if (value < DateTime.UtcNow)
throw new ArgumentOutOfRangeException(nameof(value));
if (value < DateTime.Now)
throw new ArgumentOutOfRangeException(nameof(value));
if (value < timeProvider.GetUtcNow())
throw new ArgumentOutOfRangeException(nameof(value));
if (value > someTimeProvider.GetUtcNow())
throw new ArgumentOutOfRangeException(nameof(value));
Correctly distinguishing "in the past" vs. "in the future" per type (DateTime vs. DateTimeOffset vs. DateOnly), handling .Now vs. .UtcNow (semantically different — a naive rewrite could silently change behavior for DateTime.Now, which is local time, since the throw-helper always compares against UTC/current time via TimeProvider), and supporting the optional TimeProvider overload significantly increases the risk of an incorrect rewrite compared to the other rules, which is why it was deliberately left out of the initial rule set.
Proposed solution
Design and implement a new rule (next available ID) that recognizes at least the DateTime.UtcNow/DateTimeOffset.UtcNow comparisons (skipping .Now, where a rewrite could change behavior), with a code fix rewriting to ArgumentOutOfRangeException.ThrowIfInPast/ThrowIfInFuture. Investigate whether .Now-based comparisons should be flagged separately (as a correctness issue) rather than auto-fixed.
References
Summary
NetEvolve.Arguments provides
ArgumentOutOfRangeException.ThrowIfInPast/ThrowIfInFutureoverloads forDateTime,DateTimeOffset, andDateOnly(available on .NET 8+ target frameworks), optionally accepting aTimeProvider.NetEvolve.Arguments.Analyserdoes not currently have a rule that detects the manual equivalent of these checks.Problem
The "now" side of the comparison varies significantly between codebases and has no single canonical form, e.g.:
Correctly distinguishing "in the past" vs. "in the future" per type (
DateTimevs.DateTimeOffsetvs.DateOnly), handling.Nowvs..UtcNow(semantically different — a naive rewrite could silently change behavior forDateTime.Now, which is local time, since the throw-helper always compares against UTC/current time viaTimeProvider), and supporting the optionalTimeProvideroverload significantly increases the risk of an incorrect rewrite compared to the other rules, which is why it was deliberately left out of the initial rule set.Proposed solution
Design and implement a new rule (next available ID) that recognizes at least the
DateTime.UtcNow/DateTimeOffset.UtcNowcomparisons (skipping.Now, where a rewrite could change behavior), with a code fix rewriting toArgumentOutOfRangeException.ThrowIfInPast/ThrowIfInFuture. Investigate whether.Now-based comparisons should be flagged separately (as a correctness issue) rather than auto-fixed.References
ArgumentOutOfRangeExceptionPolyfills.cs—ThrowIfInPast/ThrowIfInFutureimplementationssrc/NetEvolve.Arguments.Analyser— existing analyzer rules and test harness