15

Im my Spring Boot application, I have some controllers that accept a date as query parameter:

@RestController
public class MyController {

  @GetMapping
  public ResponseEntity<?> getDataByDate(
      @RequestParam(value = "date") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
      final LocalDate date) {
    return ResponseEntity.ok();
  }
}

This works well, and I can even mark the parameter as optional using @RequestParam(value = "date", required = false) and then use an Optional<LocalDate>. Spring will handle all this and pass an empty Optional when the parameter is missing.

Since I have several controllers using dates as query parameters, I want to configure this behavior for all LocalDate query parameters. I have tried the spring.mvc.date-pattern property, but it only seems to work for java.util.Date.

So after searching the web, the best I came up with is a ControllerAdvice I adopted from this answer. The problem with this solution is, that is can not handle Optional<LocalDate> anymore. It feels like this is the wrong way to configure the behavior in Spring Boot.

So my question is: How do I globally configure the pattern for LocalDate used as query parameters in an idiomatic way in Spring Boot?

britter
  • 1,352
  • 1
  • 11
  • 26
  • That looks like the way to do it globally using a ControllerAdvice. See also https://stackoverflow.com/questions/40644368/setting-default-datetimeformat-annotation-in-spring. – selvinsource Aug 01 '17 at 15:03
  • As I said, this solution does not handle `Optional` and it does not feel idiomatic to me. There should be some configuration property to easily set this. – britter Aug 01 '17 at 15:23
  • It looks like this it not easily possible. See https://github.com/spring-projects/spring-boot/issues/5523 – britter Aug 01 '17 at 16:35
  • so you could implement `org.springframework.core.convert.converter.GenericConverter` and doing the conversion yourself – joshiste Aug 01 '17 at 20:19

3 Answers3

11

This is currently not easily possible (e.g. by setting a simple configuration property), see #5523. The best solution I found so far is to register a Formatter<LocalDate>. This will also work with optional parameters modeled as Optional<LocalDate>:

  @Bean
  public Formatter<LocalDate> localDateFormatter() {
    return new Formatter<LocalDate>() {
      @Override
      public LocalDate parse(String text, Locale locale) throws ParseException {
        return LocalDate.parse(text, DateTimeFormatter.ISO_DATE);
      }

      @Override
      public String print(LocalDate object, Locale locale) {
        return DateTimeFormatter.ISO_DATE.format(object);
      }
    };
  }

It may become possible to set this using a configuration property when my proposal in #9930 has been merged.

britter
  • 1,352
  • 1
  • 11
  • 26
  • 1
    I've written a blog post about this: https://blog.codecentric.de/en/2017/08/parsing-of-localdate-query-parameters-in-spring-boot/ – britter Aug 07 '17 at 07:19
3

You can use spring.mvc.format.date, spring.mvc.format.time and spring.mvc.format.date-time

For example:
spring.mvc.format.time=HH:mm:ss
spring.mvc.format.date=iso
spring.mvc.format.date-time=iso-offset

as in the example above, you can use shortcuts iso аnd iso-offset from spring boot 2.4.1

Alexey Stepanov
  • 561
  • 6
  • 15
2

@britter: thanks.

spring.mvc.date-format= # Date format to use. For instance, dd/MM/yyyy works fine with Spring Boot 2.1.0.x

See # SPRING MVC (WebMvcProperties) properties.

UPDATE: But it doen't work for Spring Data Rest params ...

Grigory Kislin
  • 16,647
  • 10
  • 125
  • 197