13

I need to validate the given date has valid month, date and year. Basically, date format would be MM/dd/yyyy. But date coming like 13/40/2018 then I need to throw an error message like:

invalid start date

Is there any annotation available in spring to get this done?

@NotNull(message = ExceptionConstants.INVALID_START_DATE)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "MM/dd/yyyy")
private Date startDate;
veben
  • 19,637
  • 14
  • 60
  • 80
Saravanan
  • 11,372
  • 43
  • 143
  • 213
  • The pattern in `@JsonFormat` seems to be a `SimpleDateFormat` pattern which indicates said class is being used internally. `SimpleDateFormat` has a method to set it to non-lenient (`setLenient(false)`) to make it throw a `java.text.ParseException` for a date like this. So the question would be: how do you tell `@JsonFormat` to use a non-lenient format here? – Thomas Nov 29 '18 at 13:15
  • 2
    `@JsonFormat` already seems to have the `lenient` property as of Jackson 2.9.0: http://static.javadoc.io/com.fasterxml.jackson.core/jackson-annotations/2.9.0/com/fasterxml/jackson/annotation/JsonFormat.html - so `@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "MM/dd/yyyy", lenient = false)` should do the trick, provided that you're using Jackson 2.9.0 or higher. – Thomas Nov 29 '18 at 13:26

4 Answers4

6

You can use something like that:

@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
@JsonFormat(pattern = "MM/dd/yyyy")
private LocalDate startDate;

But I don't know if it can work with class Date

veben
  • 19,637
  • 14
  • 60
  • 80
5

You can use a custom deserializer :

public class DateDeSerializer extends StdDeserializer<Date> {

    public DateDeSerializer() {
        super(Date.class);
    }

    @Override
    public Date deserialize(JsonParser p, DeserializationContext ctxt)
        throws IOException, JsonProcessingException {
        String value = p.readValueAs(String.class);
        try {
            return new SimpleDateFormat("MM/dd/yyyy").parse(value);
        } catch (DateTimeParseException e) {
            //throw an error
        }
    }

}

and use like :

@JsonDeserialize(using = DateDeSerializer .class)
 private Date startDate;
hasnae
  • 2,137
  • 17
  • 21
4
@CustomDateValidator
private LocalDate startDate;

@Documented
@Constraint(validatedBy = CustomDateValidator.class)
@Target( { ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomDateConstraint {
    String message() default "Invalid date format";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

public class CustomDateValidator implements
  ConstraintValidator<CustomDateConstraint, LocalDate> {

    private static final String DATE_PATTERN = "MM/dd/yyyy";

    @Override
    public void initialize(CustomDateConstraint customDate) {
    }

    @Override
    public boolean isValid(LocalDate customDateField,
      ConstraintValidatorContext cxt) {
          SimpleDateFormat sdf = new SimpleDateFormat(DATE_PATTERN);
           try
        {
            sdf.setLenient(false);
            Date d = sdf.parse(customDateField);
            return true;
        }
        catch (ParseException e)
        {
            return false;
        }
    }

}
G.Noulas
  • 442
  • 6
  • 10
  • I tried your approach.. but it is showing @CustomDateValidator is not an annotation type. – Saravanan Nov 29 '18 at 13:56
  • check here for details https://www.baeldung.com/spring-mvc-custom-validator – G.Noulas Nov 29 '18 at 14:05
  • I'm almost sure that it should be `@CustomDateConstraint private LocalDate startDate;` instead of `@CustomDateValidator private LocalDate startDate;` . Already posted an update to your post @G.Noulas :-) – HakerMSL Feb 05 '23 at 17:25
-2

Try using below

@Pattern(regexp = "\d{4}-\d{2}-\d{2}", message = "Invalid date format. The expected format is yyyy-MM-dd")

Do the change in regex and message according to expectation. Note: this is applicable for String data type only. so if you can convert it to String, it would be easy for you to manage such validation.

arjun kumar
  • 467
  • 5
  • 12
  • This will not work as Pattern annotation is not applicable on field with data type "Date". By using pattern annotation, you'll get exception "javax.validation.UnexpectedTypeException" – Mayank Jain Jun 20 '23 at 13:34