Skip to content

Commit 66ae626

Browse files
committed
Only register Date converters with global format
Change JodaTimeFormatterRegistrar and DateFormatterRegistrar to only register converters for the Date and Calendar types when a global format has been defined. This means that the ObjectToObject converter will handle String->Date conversion using the deprecated Date(String) constructor (as was the case with Spring 3.1). Issue: SPR-10105
1 parent dbe3c23 commit 66ae626

File tree

4 files changed

+97
-14
lines changed

4 files changed

+97
-14
lines changed

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

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,20 +40,24 @@
4040
public class DateFormatterRegistrar implements FormatterRegistrar {
4141

4242

43-
private DateFormatter dateFormatter = new DateFormatter();
43+
private DateFormatter dateFormatter;
4444

4545

4646
public void registerFormatters(FormatterRegistry registry) {
4747
addDateConverters(registry);
48-
registry.addFormatter(this.dateFormatter);
49-
registry.addFormatterForFieldType(Calendar.class, this.dateFormatter);
5048
registry.addFormatterForFieldAnnotation(new DateTimeFormatAnnotationFormatterFactory());
49+
50+
// In order to retain back compatibility we only register Date/Calendar
51+
// types when a user defined formatter is specified (see SPR-10105)
52+
if(this.dateFormatter != null) {
53+
registry.addFormatter(this.dateFormatter);
54+
registry.addFormatterForFieldType(Calendar.class, this.dateFormatter);
55+
}
5156
}
5257

5358
/**
54-
* Set the date formatter to register. If not specified the default {@link DateFormatter}
55-
* will be used. This method can be used if additional formatter configuration is
56-
* required.
59+
* Set the date formatter to register. If not specified no formatter is registered.
60+
* This method can be used if global formatter configuration is required.
5761
* @param dateFormatter the date formatter
5862
*/
5963
public void setFormatter(DateFormatter dateFormatter) {

spring-context/src/main/java/org/springframework/format/datetime/joda/JodaTimeFormatterRegistrar.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,16 @@ public void registerFormatters(FormatterRegistry registry) {
174174
addFormatterForFields(registry,
175175
new ReadableInstantPrinter(dateTimeFormatter),
176176
new DateTimeParser(dateTimeFormatter),
177-
ReadableInstant.class, Date.class, Calendar.class);
177+
ReadableInstant.class);
178+
179+
// In order to retain back compatibility we only register Date/Calendar
180+
// types when a user defined formatter is specified (see SPR-10105)
181+
if(this.formatters.containsKey(Type.DATE_TIME)) {
182+
addFormatterForFields(registry,
183+
new ReadableInstantPrinter(dateTimeFormatter),
184+
new DateTimeParser(dateTimeFormatter),
185+
Date.class, Calendar.class);
186+
}
178187

179188
registry.addFormatterForFieldAnnotation(
180189
new JodaDateTimeFormatAnnotationFormatterFactory());

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

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@
1616

1717
package org.springframework.format.datetime;
1818

19+
import static org.hamcrest.Matchers.equalTo;
1920
import static org.junit.Assert.assertEquals;
21+
import static org.junit.Assert.assertNotNull;
22+
import static org.junit.Assert.assertThat;
2023

2124
import java.util.ArrayList;
2225
import java.util.Calendar;
@@ -50,9 +53,12 @@ public class DateFormattingTests {
5053

5154
@Before
5255
public void setUp() {
53-
DefaultConversionService.addDefaultConverters(conversionService);
54-
5556
DateFormatterRegistrar registrar = new DateFormatterRegistrar();
57+
setUp(registrar);
58+
}
59+
60+
private void setUp(DateFormatterRegistrar registrar) {
61+
DefaultConversionService.addDefaultConverters(conversionService);
5662
registrar.registerFormatters(conversionService);
5763

5864
SimpleDateBean bean = new SimpleDateBean();
@@ -187,13 +193,48 @@ public void testBindNestedDateAnnotated() {
187193
}
188194

189195
@Test
190-
public void dateToString() throws Exception {
196+
public void dateToStringWithoutGlobalFormat() throws Exception {
197+
Date date = new Date();
198+
Object actual = this.conversionService.convert(date, TypeDescriptor.valueOf(Date.class), TypeDescriptor.valueOf(String.class));
199+
String expected = date.toString();
200+
assertEquals(expected, actual);
201+
}
202+
203+
@Test
204+
public void dateToStringWithGlobalFormat() throws Exception {
205+
DateFormatterRegistrar registrar = new DateFormatterRegistrar();
206+
registrar.setFormatter(new DateFormatter());
207+
setUp(registrar);
191208
Date date = new Date();
192209
Object actual = this.conversionService.convert(date, TypeDescriptor.valueOf(Date.class), TypeDescriptor.valueOf(String.class));
193210
String expected = new DateFormatter().print(date, Locale.US);
194211
assertEquals(expected, actual);
195212
}
196213

214+
@Test
215+
@SuppressWarnings("deprecation")
216+
public void stringToDateWithoutGlobalFormat() throws Exception {
217+
// SPR-10105
218+
String string = "Sat, 12 Aug 1995 13:30:00 GM";
219+
Date date = this.conversionService.convert(string, Date.class);
220+
assertThat(date, equalTo(new Date(string)));
221+
}
222+
223+
@Test
224+
public void stringToDateWithGlobalFormat() throws Exception {
225+
// SPR-10105
226+
DateFormatterRegistrar registrar = new DateFormatterRegistrar();
227+
DateFormatter dateFormatter = new DateFormatter();
228+
dateFormatter.setIso(ISO.DATE_TIME);
229+
registrar.setFormatter(dateFormatter);
230+
setUp(registrar);
231+
// This is a format that cannot be parsed by new Date(String)
232+
String string = "2009-06-01T14:23:05.003+0000";
233+
Date date = this.conversionService.convert(string, Date.class);
234+
assertNotNull(date);
235+
}
236+
237+
197238
@SuppressWarnings("unused")
198239
private static class SimpleDateBean {
199240

spring-context/src/test/java/org/springframework/format/datetime/joda/JodaTimeFormattingTests.java

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@
1616

1717
package org.springframework.format.datetime.joda;
1818

19+
import static org.hamcrest.Matchers.equalTo;
20+
import static org.junit.Assert.assertEquals;
21+
import static org.junit.Assert.assertNotNull;
22+
import static org.junit.Assert.assertThat;
23+
1924
import java.util.ArrayList;
2025
import java.util.Calendar;
2126
import java.util.Date;
@@ -32,7 +37,6 @@
3237
import org.junit.After;
3338
import org.junit.Before;
3439
import org.junit.Test;
35-
3640
import org.springframework.beans.MutablePropertyValues;
3741
import org.springframework.context.i18n.LocaleContextHolder;
3842
import org.springframework.core.convert.TypeDescriptor;
@@ -42,8 +46,6 @@
4246
import org.springframework.format.support.FormattingConversionService;
4347
import org.springframework.validation.DataBinder;
4448

45-
import static org.junit.Assert.*;
46-
4749
/**
4850
* @author Keith Donald
4951
* @author Juergen Hoeller
@@ -459,13 +461,40 @@ public void testBindMutableDateTimeAnnotated() {
459461
}
460462

461463
@Test
462-
public void dateToString() throws Exception {
464+
public void dateToStringWithFormat() throws Exception {
465+
JodaTimeFormatterRegistrar registrar = new JodaTimeFormatterRegistrar();
466+
registrar.setDateTimeFormatter(org.joda.time.format.DateTimeFormat.shortDateTime());
467+
setUp(registrar);
463468
Date date = new Date();
464469
Object actual = this.conversionService.convert(date, TypeDescriptor.valueOf(Date.class), TypeDescriptor.valueOf(String.class));
465470
String expected = JodaTimeContextHolder.getFormatter(org.joda.time.format.DateTimeFormat.shortDateTime(), Locale.US).print(new DateTime(date));
466471
assertEquals(expected, actual);
467472
}
468473

474+
@Test
475+
@SuppressWarnings("deprecation")
476+
public void stringToDateWithoutGlobalFormat() throws Exception {
477+
// SPR-10105
478+
String string = "Sat, 12 Aug 1995 13:30:00 GM";
479+
Date date = this.conversionService.convert(string, Date.class);
480+
assertThat(date, equalTo(new Date(string)));
481+
}
482+
483+
@Test
484+
public void stringToDateWithGlobalFormat() throws Exception {
485+
// SPR-10105
486+
JodaTimeFormatterRegistrar registrar = new JodaTimeFormatterRegistrar();
487+
DateTimeFormatterFactory factory = new DateTimeFormatterFactory();
488+
factory.setIso(ISO.DATE_TIME);
489+
registrar.setDateTimeFormatter(factory.createDateTimeFormatter());
490+
setUp(registrar);
491+
// This is a format that cannot be parsed by new Date(String)
492+
String string = "2009-10-31T07:00:00.000-05:00";
493+
Date date = this.conversionService.convert(string, Date.class);
494+
assertNotNull(date);
495+
}
496+
497+
469498
@SuppressWarnings("unused")
470499
private static class JodaTimeBean {
471500

0 commit comments

Comments
 (0)