Skip to content

Commit f4dfe94

Browse files
committed
Fallback to ISO-based default java.time type parsing
Closes gh-26985
1 parent 3d83db6 commit f4dfe94

File tree

2 files changed

+76
-4
lines changed

2 files changed

+76
-4
lines changed

spring-context/src/main/java/org/springframework/format/datetime/standard/TemporalAccessorParser.java

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -77,7 +77,8 @@ public TemporalAccessorParser(Class<? extends TemporalAccessor> temporalAccessor
7777
}
7878

7979
TemporalAccessorParser(Class<? extends TemporalAccessor> temporalAccessorType, DateTimeFormatter formatter,
80-
@Nullable String[] fallbackPatterns, @Nullable Object source) {
80+
@Nullable String[] fallbackPatterns, @Nullable Object source) {
81+
8182
this.temporalAccessorType = temporalAccessorType;
8283
this.formatter = formatter;
8384
this.fallbackPatterns = fallbackPatterns;
@@ -104,10 +105,19 @@ public TemporalAccessor parse(String text, Locale locale) throws ParseException
104105
}
105106
}
106107
}
108+
else {
109+
// Fallback to ISO-based default java.time type parsing
110+
try {
111+
return defaultParse(text);
112+
}
113+
catch (DateTimeParseException ignoredException) {
114+
// Ignore fallback parsing exception like above
115+
}
116+
}
107117
if (this.source != null) {
108118
throw new DateTimeParseException(
109-
String.format("Unable to parse date time value \"%s\" using configuration from %s", text, this.source),
110-
text, ex.getErrorIndex(), ex);
119+
String.format("Unable to parse date time value \"%s\" using configuration from %s", text, this.source),
120+
text, ex.getErrorIndex(), ex);
111121
}
112122
// else rethrow original exception
113123
throw ex;
@@ -148,4 +158,37 @@ else if (MonthDay.class == this.temporalAccessorType) {
148158
}
149159
}
150160

161+
private TemporalAccessor defaultParse(String text) throws DateTimeParseException {
162+
if (Instant.class == this.temporalAccessorType) {
163+
return Instant.parse(text);
164+
}
165+
else if (LocalDate.class == this.temporalAccessorType) {
166+
return LocalDate.parse(text);
167+
}
168+
else if (LocalTime.class == this.temporalAccessorType) {
169+
return LocalTime.parse(text);
170+
}
171+
else if (LocalDateTime.class == this.temporalAccessorType) {
172+
return LocalDateTime.parse(text);
173+
}
174+
else if (ZonedDateTime.class == this.temporalAccessorType) {
175+
return ZonedDateTime.parse(text);
176+
}
177+
else if (OffsetDateTime.class == this.temporalAccessorType) {
178+
return OffsetDateTime.parse(text);
179+
}
180+
else if (OffsetTime.class == this.temporalAccessorType) {
181+
return OffsetTime.parse(text);
182+
}
183+
else if (YearMonth.class == this.temporalAccessorType) {
184+
return YearMonth.parse(text);
185+
}
186+
else if (MonthDay.class == this.temporalAccessorType) {
187+
return MonthDay.parse(text);
188+
}
189+
else {
190+
throw new IllegalStateException("Unsupported TemporalAccessor type: " + this.temporalAccessorType);
191+
}
192+
}
193+
151194
}

spring-context/src/test/java/org/springframework/format/datetime/standard/DateTimeFormattingTests.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,15 @@ void testBindLocalDate() {
110110
assertThat(binder.getBindingResult().getFieldValue("localDate")).isEqualTo("10/31/09");
111111
}
112112

113+
@Test
114+
void testBindLocalDateWithISO() {
115+
MutablePropertyValues propertyValues = new MutablePropertyValues();
116+
propertyValues.add("localDate", "2009-10-31");
117+
binder.bind(propertyValues);
118+
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
119+
assertThat(binder.getBindingResult().getFieldValue("localDate")).isEqualTo("10/31/09");
120+
}
121+
113122
@Test
114123
void testBindLocalDateWithSpecificStyle() {
115124
DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
@@ -207,6 +216,15 @@ void testBindLocalTime() {
207216
assertThat(binder.getBindingResult().getFieldValue("localTime")).isEqualTo("12:00 PM");
208217
}
209218

219+
@Test
220+
void testBindLocalTimeWithISO() {
221+
MutablePropertyValues propertyValues = new MutablePropertyValues();
222+
propertyValues.add("localTime", "12:00:00");
223+
binder.bind(propertyValues);
224+
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
225+
assertThat(binder.getBindingResult().getFieldValue("localTime")).isEqualTo("12:00 PM");
226+
}
227+
210228
@Test
211229
void testBindLocalTimeWithSpecificStyle() {
212230
DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
@@ -260,6 +278,17 @@ void testBindLocalDateTime() {
260278
assertThat(value.endsWith("12:00 PM")).isTrue();
261279
}
262280

281+
@Test
282+
void testBindLocalDateTimeWithISO() {
283+
MutablePropertyValues propertyValues = new MutablePropertyValues();
284+
propertyValues.add("localDateTime", "2009-10-31T12:00:00");
285+
binder.bind(propertyValues);
286+
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
287+
String value = binder.getBindingResult().getFieldValue("localDateTime").toString();
288+
assertThat(value.startsWith("10/31/09")).isTrue();
289+
assertThat(value.endsWith("12:00 PM")).isTrue();
290+
}
291+
263292
@Test
264293
void testBindLocalDateTimeAnnotated() {
265294
MutablePropertyValues propertyValues = new MutablePropertyValues();

0 commit comments

Comments
 (0)