diff --git a/spring-context/src/main/java/org/springframework/format/datetime/standard/Jsr310DateTimeFormatAnnotationFormatterFactory.java b/spring-context/src/main/java/org/springframework/format/datetime/standard/Jsr310DateTimeFormatAnnotationFormatterFactory.java index a1fd17fe21f..4c112bfc27f 100644 --- a/spring-context/src/main/java/org/springframework/format/datetime/standard/Jsr310DateTimeFormatAnnotationFormatterFactory.java +++ b/spring-context/src/main/java/org/springframework/format/datetime/standard/Jsr310DateTimeFormatAnnotationFormatterFactory.java @@ -19,8 +19,10 @@ package org.springframework.format.datetime.standard; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; +import java.time.MonthDay; import java.time.OffsetDateTime; import java.time.OffsetTime; +import java.time.YearMonth; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.temporal.TemporalAccessor; @@ -43,6 +45,7 @@ import org.springframework.util.StringUtils; * * @author Juergen Hoeller * @author Sam Brannen + * @author Kazuki Shimizu * @since 4.0 * @see org.springframework.format.annotation.DateTimeFormat */ @@ -60,10 +63,11 @@ public class Jsr310DateTimeFormatAnnotationFormatterFactory extends EmbeddedValu fieldTypes.add(ZonedDateTime.class); fieldTypes.add(OffsetDateTime.class); fieldTypes.add(OffsetTime.class); + fieldTypes.add(YearMonth.class); + fieldTypes.add(MonthDay.class); FIELD_TYPES = Collections.unmodifiableSet(fieldTypes); } - @Override public final Set> getFieldTypes() { return FIELD_TYPES; diff --git a/spring-context/src/main/java/org/springframework/format/datetime/standard/TemporalAccessorParser.java b/spring-context/src/main/java/org/springframework/format/datetime/standard/TemporalAccessorParser.java index b8dd20fe019..cea8340132d 100644 --- a/spring-context/src/main/java/org/springframework/format/datetime/standard/TemporalAccessorParser.java +++ b/spring-context/src/main/java/org/springframework/format/datetime/standard/TemporalAccessorParser.java @@ -20,8 +20,10 @@ import java.text.ParseException; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; +import java.time.MonthDay; import java.time.OffsetDateTime; import java.time.OffsetTime; +import java.time.YearMonth; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; @@ -38,6 +40,7 @@ import org.springframework.util.ObjectUtils; * * @author Juergen Hoeller * @author Sam Brannen + * @author Kazuki Shimizu * @since 4.0 * @see DateTimeContextHolder#getFormatter * @see java.time.LocalDate#parse(CharSequence, java.time.format.DateTimeFormatter) @@ -46,6 +49,8 @@ import org.springframework.util.ObjectUtils; * @see java.time.ZonedDateTime#parse(CharSequence, java.time.format.DateTimeFormatter) * @see java.time.OffsetDateTime#parse(CharSequence, java.time.format.DateTimeFormatter) * @see java.time.OffsetTime#parse(CharSequence, java.time.format.DateTimeFormatter) + * @see java.time.YearMonth#parse(CharSequence, java.time.format.DateTimeFormatter) + * @see java.time.MonthDay#parse(CharSequence, java.time.format.DateTimeFormatter) */ public final class TemporalAccessorParser implements Parser { @@ -128,6 +133,12 @@ public final class TemporalAccessorParser implements Parser { else if (OffsetTime.class == this.temporalAccessorType) { return OffsetTime.parse(text, formatterToUse); } + else if (YearMonth.class == this.temporalAccessorType) { + return YearMonth.parse(text, formatterToUse); + } + else if (MonthDay.class == this.temporalAccessorType) { + return MonthDay.parse(text, formatterToUse); + } else { throw new IllegalStateException("Unsupported TemporalAccessor type: " + this.temporalAccessorType); } diff --git a/spring-context/src/test/java/org/springframework/format/datetime/standard/DateTimeFormattingTests.java b/spring-context/src/test/java/org/springframework/format/datetime/standard/DateTimeFormattingTests.java index 23a62770fdf..1fe57b428c5 100644 --- a/spring-context/src/test/java/org/springframework/format/datetime/standard/DateTimeFormattingTests.java +++ b/spring-context/src/test/java/org/springframework/format/datetime/standard/DateTimeFormattingTests.java @@ -64,6 +64,7 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Juergen Hoeller * @author Phillip Webb * @author Sam Brannen + * @author Kazuki Shimizu */ class DateTimeFormattingTests { @@ -467,6 +468,16 @@ class DateTimeFormattingTests { assertThat(binder.getBindingResult().getFieldValue("yearMonth").toString().equals("2007-12")).isTrue(); } + @Test + public void testBindYearMonthAnnotatedPattern() { + MutablePropertyValues propertyValues = new MutablePropertyValues(); + propertyValues.add("yearMonthAnnotatedPattern", "12/2007"); + binder.bind(propertyValues); + assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0); + assertThat(binder.getBindingResult().getFieldValue("yearMonthAnnotatedPattern")).isEqualTo("12/2007"); + assertThat(binder.getBindingResult().getRawFieldValue("yearMonthAnnotatedPattern")).isEqualTo(YearMonth.parse("2007-12")); + } + @Test void testBindMonthDay() { MutablePropertyValues propertyValues = new MutablePropertyValues(); @@ -476,6 +487,16 @@ class DateTimeFormattingTests { assertThat(binder.getBindingResult().getFieldValue("monthDay").toString().equals("--12-03")).isTrue(); } + @Test + public void testBindMonthDayAnnotatedPattern() { + MutablePropertyValues propertyValues = new MutablePropertyValues(); + propertyValues.add("monthDayAnnotatedPattern", "1/3"); + binder.bind(propertyValues); + assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0); + assertThat(binder.getBindingResult().getFieldValue("monthDayAnnotatedPattern")).isEqualTo("1/3"); + assertThat(binder.getBindingResult().getRawFieldValue("monthDayAnnotatedPattern")).isEqualTo(MonthDay.parse("--01-03")); + } + @Nested class FallbackPatternTests { @@ -611,8 +632,14 @@ class DateTimeFormattingTests { private YearMonth yearMonth; + @DateTimeFormat(pattern="MM/uuuu") + private YearMonth yearMonthAnnotatedPattern; + private MonthDay monthDay; + @DateTimeFormat(pattern="M/d") + private MonthDay monthDayAnnotatedPattern; + private final List children = new ArrayList<>(); @@ -775,6 +802,14 @@ class DateTimeFormattingTests { this.yearMonth = yearMonth; } + public YearMonth getYearMonthAnnotatedPattern() { + return yearMonthAnnotatedPattern; + } + + public void setYearMonthAnnotatedPattern(YearMonth yearMonthAnnotatedPattern) { + this.yearMonthAnnotatedPattern = yearMonthAnnotatedPattern; + } + public MonthDay getMonthDay() { return this.monthDay; } @@ -783,6 +818,14 @@ class DateTimeFormattingTests { this.monthDay = monthDay; } + public MonthDay getMonthDayAnnotatedPattern() { + return monthDayAnnotatedPattern; + } + + public void setMonthDayAnnotatedPattern(MonthDay monthDayAnnotatedPattern) { + this.monthDayAnnotatedPattern = monthDayAnnotatedPattern; + } + public List getChildren() { return this.children; }