Tuesday, June 3, 2014

Spring 4: @DateTimeFormat with Java 8 Date-Time API

@DateTimeFormat annotation that was introduced in Spring 3.0 as a part of Formatter SPI can be used to to parse and print localized field values in web applications. In Spring 4.0, @DateTimeFormat annotation can be used with Java 8 Date-Time API (java.time) out-of-the-box, without extra effort.

In Spring, field formatting can be configured by field type or annotation. To bind an annotation to a formatter AnnotationFormatterFactory must be implemented. Spring 4.0 brings Jsr310DateTimeFormatAnnotationFormatterFactory that formats Java 8 Date-Time fields annotated with the @DateTimeFormat. Supported field types are as follows:

  • java.time.LocalDate
  • java.time.LocalTime
  • java.time.LocalDateTime
  • java.time.ZonedDateTime
  • java.time.OffsetDateTime
  • java.time.OffsetTime

One can utilize all mentioned types in a form like below:


public class DatesForm {

    @DateTimeFormat(iso = ISO.DATE)
    private LocalDate localDate;

    @DateTimeFormat(iso = ISO.TIME)
    private LocalTime localTime;

    @DateTimeFormat(iso = ISO.TIME)
    private OffsetTime offsetTime;

    @DateTimeFormat(iso = ISO.DATE_TIME)
    private LocalDateTime localDateTime;

    @DateTimeFormat(iso = ISO.DATE_TIME)
    private ZonedDateTime zonedDateTime;

    @DateTimeFormat(iso = ISO.DATE_TIME)
    private OffsetDateTime offsetDateTime;
    
}


The form can be passed to the view and Spring will take care of proper formatting of the fields.

While specifying the formatting on the fields of types: java.time.LocalDate, java.time.LocalTime, java.time.OffsetTime you need to remember to properly configure @DateTimeFormat.

@DateTimeFormat declares that a field should be formatted as a date time and since java.time.LocalDate represents a date, and the other two represent time - you will get java.time.temporal.UnsupportedTemporalTypeException (e.g.: Unsupported field: ClockHourOfAmPm, Unsupported field: MonthOfYear) thrown by java.time.format.DateTimeFormatter.

6 comments:

  1. Thanks for your post. Just replace java.util -> java.time.

    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete
  3. Hi.

    I want to use the DateTimeFormat annotation on java.time. types. But it seem that spring is ignore this declaration on this types. With java.util.Date its works fine, but not with the java.time types. I use Spring 4.1.4 and add the JSR310-FormatFactory as FormatterForAnnotations in my java config for Spring.

    @DateTimeFormat(style = "M-") <--- ignored
    private LocalDate availableFrom;

    @DateTimeFormat(style = "M-") <--- works
    private Date availableFromTest;


    My configuration:

    @Override
    public void addFormatters(FormatterRegistry registry) {
    registry.addFormatterForFieldAnnotation(new Jsr310DateTimeFormatAnnotationFormatterFactory());
    }


    The LocalDate field always formatted as yyyy-MM-dd and not as the locale (de) define (dd.MM.yyyy).

    Do i miss something in my configuration?

    regards Rizzi

    ReplyDelete
  4. Sorry for my Spam :D
    i found the problem. i forgotten to remove the custom converters from the init binder :/

    ReplyDelete