1. Introduction

In this short tutorial, we’ll learn how to accept Date, LocalDate, and LocalDateTime parameters in Spring REST requests, both at the request and application level.

2. The Problem

Let’s consider a controller with three methods that accepts Date, LocalDate and LocalDateTime parameters:

@RestController
public class DateTimeController {

    @PostMapping("/date")
    public void date(@RequestParam("date") Date date) {
        // ...
    }

    @PostMapping("/localdate")
    public void localDate(@RequestParam("localDate") LocalDate localDate) {
        // ...
    }

    @PostMapping("/localdatetime")
    public void dateTime(@RequestParam("localDateTime") LocalDateTime localDateTime) {
        // ...
    }
}

When sending a POST request to any of those methods with a parameter formatted in accordance with ISO 8601, we’ll get an exception.

For example, when sending “2018-10-22” to the /date endpoint, we’ll get a bad request error with a message similar to this:

Failed to convert value of type 'java.lang.String' to required type 'java.time.LocalDate'; 
  nested exception is org.springframework.core.convert.ConversionFailedException.

This is because by default, Spring cannot convert String parameters to any date or time object.

3. Convert Date Parameters on Request Level

One of the ways to handle this problem is to annotate the parameters with the @DateTimeFormat annotation, and provide a formatting pattern parameter:

@RestController
public class DateTimeController {

    @PostMapping("/date")
    public void date(@RequestParam("date") 
      @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) Date date) {
        // ...
    }

    @PostMapping("/local-date")
    public void localDate(@RequestParam("localDate") 
      @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate localDate) {
        // ...
    }

    @PostMapping("/local-date-time")
    public void dateTime(@RequestParam("localDateTime") 
      @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime localDateTime) {
        // ...
    }
}

This way the Strings will be properly converted to date objects, provided the Strings are formatted using the ISO 8601 format.

We can also use our own conversion patterns by providing a pattern parameter in the @DateTimeFormat annotation:

@PostMapping("/date")
public void date(@RequestParam("date") 
  @DateTimeFormat(pattern = "dd.MM.yyyy") Date date) {
    // ...
}

4. Convert Date Parameters at the Application Level

Another way to handle date and time object conversion in Spring is to provide a global configuration. By following the official documentation, we should extend the WebMvcConfigurationSupport configuration and its mvcConversionService method:

@Configuration
public class DateTimeConfig extends WebMvcConfigurationSupport {

    @Bean
    @Override
    public FormattingConversionService mvcConversionService() {
        DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService(false);

        DateTimeFormatterRegistrar dateTimeRegistrar = new DateTimeFormatterRegistrar();
        dateTimeRegistrar.setDateFormatter(DateTimeFormatter.ofPattern("dd.MM.yyyy"));
        dateTimeRegistrar.setDateTimeFormatter(DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss"));
        dateTimeRegistrar.registerFormatters(conversionService);

        DateFormatterRegistrar dateRegistrar = new DateFormatterRegistrar();
        dateRegistrar.setFormatter(new DateFormatter("dd.MM.yyyy"));
        dateRegistrar.registerFormatters(conversionService);

        return conversionService;
    }
}

First, we create DefaultFormattingConversionService with a false parameter, which means Spring won’t register any formatters by default.

Then we need to register our custom formats for date and date-time parameters. We do this by registering two custom formatting registrars. The first one, DateTimeFormatterRegistar, will be responsible for parsing the LocalDate and LocaDateTime objects. The second one, DateFormattingRegistrar, will handle the Date object.

5. Configure Date-Time in Properties File

Spring also gives us the option to set global date-time formats via the application properties file. There are three individual parameters for the date, date-time, and time format:

spring.mvc.format.date=yyyy-MM-dd
spring.mvc.format.date-time=yyyy-MM-dd HH:mm:ss
spring.mvc.format.time=HH:mm:ss

All of these parameters can be replaced with an iso value. For example, setting the date-time parameter as:

spring.mvc.format.date-time=iso

will be equal to ISO-8601 formatting:

spring.mvc.format.date-time=yyyy-MM-dd HH:mm:ss

6. Conclusion

In this article, we learned how to accept the date parameters in Spring MVC requests. We discussed how to do this per request, and globally.

We also learned how to create our own date formatting patterns.

As always, all source code is available over on GitHub.