Richard Nienaber
Richard Nienaber

Reputation: 10564

How to validate a string as DateTime using FluentValidation

With FluentValidation, is it possible to validate a string as a parseable DateTime without having to specify a Custom() delegate?

Ideally, I'd like to say something like the EmailAddress function, e.g.:

RuleFor(s => s.EmailAddress).EmailAddress().WithMessage("Invalid email address");

So something like this:

RuleFor(s => s.DepartureDateTime).DateTime().WithMessage("Invalid date/time");

Upvotes: 19

Views: 23241

Answers (4)

Dariusz Woźniak
Dariusz Woźniak

Reputation: 10350

Yet another approach, the answer I gave in the Fluent Validation - Date format yyyy-mm-dd answer:

public static IRuleBuilderOptions<T, string> MustBeDateTimeOfFormat<T>(this IRuleBuilder<T, string> ruleBuilder, string format)
{
    return ruleBuilder.Must(x => DateTime.TryParseExact(x, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out _));
}

And then, you may use it in your validator class:

RuleFor(x => x.DateOfBirth).MustBeDateTimeOfFormat("yyyy-MM-dd");

Read more at:

Upvotes: 0

Darin Dimitrov
Darin Dimitrov

Reputation: 1038770

RuleFor(s => s.DepartureDateTime)
    .Must(BeAValidDate)
    .WithMessage("Invalid date/time");

and:

private bool BeAValidDate(string value)
{
    DateTime date;
    return DateTime.TryParse(value, out date);
}

or you could write a custom extension method.

Upvotes: 40

tdbeckett
tdbeckett

Reputation: 708

You can do it exactly the same way that EmailAddress was done.

http://fluentvalidation.codeplex.com/wikipage?title=Custom

public class DateTimeValidator<T> : PropertyValidator
{
    public DateTimeValidator() : base("The value provided is not a valid date") { }

    protected override bool IsValid(PropertyValidatorContext context)
    {
        if (context.PropertyValue == null) return true;

        if (context.PropertyValue as string == null) return false;

        DateTime buffer;
        return DateTime.TryParse(context.PropertyValue as string, out buffer);
    }
}

public static class StaticDateTimeValidator
{
    public static IRuleBuilderOptions<T, TProperty> IsValidDateTime<T, TProperty>(this IRuleBuilder<T, TProperty> ruleBuilder)
    {
        return ruleBuilder.SetValidator(new DateTimeValidator<TProperty>());
    }
}

And then

public class PersonValidator : AbstractValidator<IPerson>
{
    /// <summary>
    /// Initializes a new instance of the <see cref="PersonValidator"/> class.
    /// </summary>
    public PersonValidator()
    {
        RuleFor(person => person.DateOfBirth).IsValidDateTime();   

    }
}

Upvotes: 4

Mohamed Emad
Mohamed Emad

Reputation: 1133

If s.DepartureDateTime is already a DateTime property; it's nonsense to validate it as DateTime. But if it a string, Darin's answer is the best.

Another thing to add, Suppose that you need to move the BeAValidDate() method to an external static class, in order to not repeat the same method in every place. If you chose so, you'll need to modify Darin's rule to be:

RuleFor(s => s.DepartureDateTime)
    .Must(d => BeAValidDate(d))
    .WithMessage("Invalid date/time");

Upvotes: 3

Related Questions