Skip to content

Instantly share code, notes, and snippets.

@karenpayneoregon
Created October 1, 2025 14:45
Show Gist options
  • Select an option

  • Save karenpayneoregon/db70d5955870658ecf91e24b897279a9 to your computer and use it in GitHub Desktop.

Select an option

Save karenpayneoregon/db70d5955870658ecf91e24b897279a9 to your computer and use it in GitHub Desktop.
FluentValidation extension for nullable DateOnly

Using on a nullable DateOnly

RuleFor(x => x.DateOfBirth).DateRangeNotNullRule();

Partial model

public class Customer
{
    [Display(Name = "Birth date")]
    public DateOnly? DateOfBirth { get; set; }
}

Method docs

Done using JetBrain document AI assistant.

using FluentValidation;
namespace FluentWebApplication1.Validators;
public static class RuleBuilderExtensions
{
/// <summary>
/// Adds a validation rule to ensure that a nullable <see cref="DateOnly"/> property is not null
/// and falls within a valid date range.
/// </summary>
/// <typeparam name="T">The type of the object being validated.</typeparam>
/// <param name="ruleBuilder">The rule builder for the property being validated.</param>
/// <returns>
/// An <see cref="IRuleBuilderOptions{T, TProperty}"/> that can be used to chain additional validation rules.
/// </returns>
/// <remarks>
/// The valid date range is defined as being after 120 years ago and on or before today's date.
/// If the property is null, only the "not null" validation rule will be triggered.
/// </remarks>
public static IRuleBuilderOptions<T, DateOnly?> DateRangeNotNullRule<T>(this IRuleBuilder<T, DateOnly?> ruleBuilder)
{
var today = DateOnly.FromDateTime(DateTime.Today);
var minDate = DateOnly.FromDateTime(DateTime.Today.AddYears(-120));
return ruleBuilder
.NotNull().WithMessage("'{PropertyName}' is required.")
// Only run range check when there's a value to avoid duplicate errors
.Must(x => x == null || (x.Value > minDate && x.Value <= today))
.WithMessage($"'{{PropertyName}}' must be after {minDate} and on or before {today}.");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment