-1

I have below property in POJO -

@NotNull(message = "dateOfBirth is required")
@DateFormat(format = "YYYY-MM-DD", message = "dateOfBirth should be in format YYYY-MM-DD")
@JsonDeserialize(using = LocalDateDeserializer.class)
LocalDate dateOfBirth;

For custom message of validation I have added below validator -

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

public class DateFormatValidator implements ConstraintValidator<DateFormat, LocalDate> {

private String dateFormat;

@Override
public void initialize(DateFormat constraintAnnotation){
    this.dateFormat = constraintAnnotation.format();
}

@Override
public boolean isValid(LocalDate value, ConstraintValidatorContext context) {
    SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
    try{
        sdf.setLenient(false);
        Date d = sdf.parse(String.valueOf(value));
        return true;
    }catch(ParseException e) {
        return false;
    }
}

}

Now for my junit I am adding -

.dateOfBirth(LocalDate.of(1984, 03, 12))

but when I run my junit, I am getting my validator message means dateOfBirth should be in format YYYY-MM-DD. How can I pass date into my junit to satisfy above condition and should run junit.

ppb
  • 2,299
  • 4
  • 43
  • 75

2 Answers2

0

This doesn't make sense for several reasons.

First, because YYYY-MM-DD means "week year", then month, then "day in year". Nobody will ever enter a date in that format. You probably mean yyyy-MM-dd.

Second, because using the old, obsolete SimpleDateFormat and Date classes instead of the new, well-thought java.time package classes to parse dates is really a strange idea.

And most importantly, because a LocalDate doesn't have a format. So you can't validate that a LocalDate has the right format. A LocalDate is not a String. Whatever format you use to parse a String into a LocalDate, in the end, you end up with a LocalDate, which doesn't remember the format of the original parsed String you used. Just like when you have an Integer, you can't possibly know if the user who entered that integer did it in decimal format, or in binary, or in hexadecimal. That parsing happened before the Integer was created, and the Integer object only contains the value of the int, not its original format on the JSON structure.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • thanks for your reply. Can you let me know how we can achieve same functionality by using new java8 date APIs. – ppb Aug 06 '19 at 06:40
0

I think that you are over-thinking your issue. You are trying to write stuff that already done for you automatically. First of all you have a wrong format - most likely you mean "yyyy-MM-dd" - See the explanation here: DateTimeFormatter. Second - all you will need to do is:

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ")
public ZonedDateTime getTime() {
    return time;
}

For more details see the answers here and may be here

Michael Gantman
  • 7,315
  • 2
  • 19
  • 36
  • How we can add custom error message to @JsonFormat if I put invalid date. If I put invalid date e.g. 2019-02-31 then it printing whole stack strace, so instead of this how can I print custom message like Invalid Date. – ppb Aug 06 '19 at 15:21
  • Not sure, but if it is your code that does conversion, then you can catch the exception and print anything you want. Also you may want to look into custom JSON de-serializers and that might help – Michael Gantman Aug 06 '19 at 15:39