Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Common Pitfall: Why DateTime.Now Returns an Incorrect Past Date

Tech 1

When validating a user's date of birth with FluentValidation, comparing the input against DateTime.Now.Date can produce unexpected results: an error may incorrectly state that the input date (e.g. 2020-07-06) cannot be after the current date, even when the actual current date is 2020-07-08, and the input date was correctly passed from the client.

To understand why this happens, look at the following validation class implementation:

class DateValidator
{
    private readonly DateTime _maxAllowedTime;

    public DateValidator(DateTime maxDate)
    {
        _maxAllowedTime = maxDate;
    }

    public bool ValidateDate(DateTime inputDate)
    {
        return inputDate <= _maxAllowedTime;
    }
}

When creating an instance and running validation like this:

var validator = new DateValidator(DateTime.Now);
bool validationResult = validator.ValidateDate(DateTime.Now);

The result is often false if there is any delay between instantiation and validation, rather than the expected true. Now compare this to an alternative implementation:

class DateValidatorWithDynamicEvaluation
{
    private readonly Expression<Func<DateTime>> _maxDateExpression;

    public DateValidatorWithDynamicEvaluation(Expression<Func<DateTime>> maxDateSelector)
    {
        _maxDateExpression = maxDateSelector;
    }

    public bool ValidateDate(DateTime inputDate)
    {
        return inputDate <= _maxDateExpression.Compile()();
    }
}

Used like this:

var dynamicValidator = new DateValidatorWithDynamicEvaluation(() => DateTime.Now);
bool dynamicValidationResult = dynamicValidator.ValidateDate(DateTime.Now);

This implementation consistently returns true as expected.

The root cause of the bug in the first implementation is straightforward: when you pass DateTime.Now as a constructor parameter, the value is evaluated immediately at the moment the constructor executes. That fixed snapshot of time is then stored in the readonly _maxAllowedTime field, and it never updates.

If your validator is a long-lived, singleton, or reused instance (a common pattern in validation libraries like FluentValidation), the stored time will stay as the time when the app started or the validator was first created, which becomes a date in the past as time passes. This matches the original issue: the validator was created on 2020-07-06, and when it was reused two days later, it still used the 2020-07-06 value as "current date".

In the dynamic implementatino, you do not store an evaluated time value. Instead, you store an expression that describes how to get the current time. Every time validation runs, the expression is compiled and invoked, which calls DateTime.Now at that exact moment, producing the correct up-to-date current time.

Key takeaways to avoid this pitfall:

  1. Always treat DateTime.Now and other time-dependent dynamic values as snapshot values, not dynamic references.
  2. Any time you store the result of DateTime.Now in a variable or field, it becomes a fixed static value that will never update automatically.
  3. When you need to access the actual current time at the time of logic execution, always wrap DateTime.Now in a deleagte or expression that evaluates it on demand, such as Func<DateTime> or Expression<Func<DateTime>>.
Tags: C#.NET

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.