提交 1ae17c27 编写于 作者: J Juergen Hoeller

Efficient ISO_LOCAL_* variants for printing LocalDate/LocalTime/LocalDateTime

Issue: SPR-14958
上级 5458a427
...@@ -29,7 +29,7 @@ import java.time.YearMonth; ...@@ -29,7 +29,7 @@ import java.time.YearMonth;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle; import java.time.format.FormatStyle;
import java.util.HashMap; import java.util.EnumMap;
import java.util.Map; import java.util.Map;
import org.springframework.format.FormatterRegistrar; import org.springframework.format.FormatterRegistrar;
...@@ -56,18 +56,17 @@ public class DateTimeFormatterRegistrar implements FormatterRegistrar { ...@@ -56,18 +56,17 @@ public class DateTimeFormatterRegistrar implements FormatterRegistrar {
/** /**
* User defined formatters. * User-defined formatters.
*/ */
private final Map<Type, DateTimeFormatter> formatters = new HashMap<>(); private final Map<Type, DateTimeFormatter> formatters = new EnumMap<>(Type.class);
/** /**
* Factories used when specific formatters have not been specified. * Factories used when specific formatters have not been specified.
*/ */
private final Map<Type, DateTimeFormatterFactory> factories; private final Map<Type, DateTimeFormatterFactory> factories = new EnumMap<>(Type.class);
public DateTimeFormatterRegistrar() { public DateTimeFormatterRegistrar() {
this.factories = new HashMap<>();
for (Type type : Type.values()) { for (Type type : Type.values()) {
this.factories.put(type, new DateTimeFormatterFactory()); this.factories.put(type, new DateTimeFormatterFactory());
} }
...@@ -155,33 +154,38 @@ public class DateTimeFormatterRegistrar implements FormatterRegistrar { ...@@ -155,33 +154,38 @@ public class DateTimeFormatterRegistrar implements FormatterRegistrar {
public void registerFormatters(FormatterRegistry registry) { public void registerFormatters(FormatterRegistry registry) {
DateTimeConverters.registerConverters(registry); DateTimeConverters.registerConverters(registry);
DateTimeFormatter dateFormatter = getFormatter(Type.DATE); DateTimeFormatter df = getFormatter(Type.DATE);
DateTimeFormatter timeFormatter = getFormatter(Type.TIME); DateTimeFormatter tf = getFormatter(Type.TIME);
DateTimeFormatter dateTimeFormatter = getFormatter(Type.DATE_TIME); DateTimeFormatter dtf = getFormatter(Type.DATE_TIME);
// Efficient ISO_LOCAL_* variants for printing since they are twice as fast...
registry.addFormatterForFieldType(LocalDate.class, registry.addFormatterForFieldType(LocalDate.class,
new TemporalAccessorPrinter(dateFormatter), new TemporalAccessorPrinter(
new TemporalAccessorParser(LocalDate.class, dateFormatter)); df == DateTimeFormatter.ISO_DATE ? DateTimeFormatter.ISO_LOCAL_DATE : df),
new TemporalAccessorParser(LocalDate.class, df));
registry.addFormatterForFieldType(LocalTime.class, registry.addFormatterForFieldType(LocalTime.class,
new TemporalAccessorPrinter(timeFormatter), new TemporalAccessorPrinter(
new TemporalAccessorParser(LocalTime.class, timeFormatter)); tf == DateTimeFormatter.ISO_TIME ? DateTimeFormatter.ISO_LOCAL_TIME : tf),
new TemporalAccessorParser(LocalTime.class, tf));
registry.addFormatterForFieldType(LocalDateTime.class, registry.addFormatterForFieldType(LocalDateTime.class,
new TemporalAccessorPrinter(dateTimeFormatter), new TemporalAccessorPrinter(
new TemporalAccessorParser(LocalDateTime.class, dateTimeFormatter)); dtf == DateTimeFormatter.ISO_DATE_TIME ? DateTimeFormatter.ISO_LOCAL_DATE_TIME : dtf),
new TemporalAccessorParser(LocalDateTime.class, dtf));
registry.addFormatterForFieldType(ZonedDateTime.class, registry.addFormatterForFieldType(ZonedDateTime.class,
new TemporalAccessorPrinter(dateTimeFormatter), new TemporalAccessorPrinter(dtf),
new TemporalAccessorParser(ZonedDateTime.class, dateTimeFormatter)); new TemporalAccessorParser(ZonedDateTime.class, dtf));
registry.addFormatterForFieldType(OffsetDateTime.class, registry.addFormatterForFieldType(OffsetDateTime.class,
new TemporalAccessorPrinter(dateTimeFormatter), new TemporalAccessorPrinter(dtf),
new TemporalAccessorParser(OffsetDateTime.class, dateTimeFormatter)); new TemporalAccessorParser(OffsetDateTime.class, dtf));
registry.addFormatterForFieldType(OffsetTime.class, registry.addFormatterForFieldType(OffsetTime.class,
new TemporalAccessorPrinter(timeFormatter), new TemporalAccessorPrinter(tf),
new TemporalAccessorParser(OffsetTime.class, timeFormatter)); new TemporalAccessorParser(OffsetTime.class, tf));
registry.addFormatterForFieldType(Instant.class, new InstantFormatter()); registry.addFormatterForFieldType(Instant.class, new InstantFormatter());
registry.addFormatterForFieldType(Period.class, new PeriodFormatter()); registry.addFormatterForFieldType(Period.class, new PeriodFormatter());
......
...@@ -68,6 +68,24 @@ public class Jsr310DateTimeFormatAnnotationFormatterFactory extends EmbeddedValu ...@@ -68,6 +68,24 @@ public class Jsr310DateTimeFormatAnnotationFormatterFactory extends EmbeddedValu
@Override @Override
public Printer<?> getPrinter(DateTimeFormat annotation, Class<?> fieldType) { public Printer<?> getPrinter(DateTimeFormat annotation, Class<?> fieldType) {
DateTimeFormatter formatter = getFormatter(annotation, fieldType); DateTimeFormatter formatter = getFormatter(annotation, fieldType);
// Efficient ISO_LOCAL_* variants for printing since they are twice as fast...
if (formatter == DateTimeFormatter.ISO_DATE) {
if (isLocal(fieldType)) {
formatter = DateTimeFormatter.ISO_LOCAL_DATE;
}
}
else if (formatter == DateTimeFormatter.ISO_TIME) {
if (isLocal(fieldType)) {
formatter = DateTimeFormatter.ISO_LOCAL_TIME;
}
}
else if (formatter == DateTimeFormatter.ISO_DATE_TIME) {
if (isLocal(fieldType)) {
formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
}
}
return new TemporalAccessorPrinter(formatter); return new TemporalAccessorPrinter(formatter);
} }
...@@ -81,7 +99,7 @@ public class Jsr310DateTimeFormatAnnotationFormatterFactory extends EmbeddedValu ...@@ -81,7 +99,7 @@ public class Jsr310DateTimeFormatAnnotationFormatterFactory extends EmbeddedValu
/** /**
* Factory method used to create a {@link DateTimeFormatter}. * Factory method used to create a {@link DateTimeFormatter}.
* @param annotation the format annotation for the field * @param annotation the format annotation for the field
* @param fieldType the type of field * @param fieldType the declared type of the field
* @return a {@link DateTimeFormatter} instance * @return a {@link DateTimeFormatter} instance
*/ */
protected DateTimeFormatter getFormatter(DateTimeFormat annotation, Class<?> fieldType) { protected DateTimeFormatter getFormatter(DateTimeFormat annotation, Class<?> fieldType) {
...@@ -92,4 +110,8 @@ public class Jsr310DateTimeFormatAnnotationFormatterFactory extends EmbeddedValu ...@@ -92,4 +110,8 @@ public class Jsr310DateTimeFormatAnnotationFormatterFactory extends EmbeddedValu
return factory.createDateTimeFormatter(); return factory.createDateTimeFormatter();
} }
private boolean isLocal(Class<?> fieldType) {
return fieldType.getSimpleName().startsWith("Local");
}
} }
...@@ -311,6 +311,15 @@ public class DateTimeFormattingTests { ...@@ -311,6 +311,15 @@ public class DateTimeFormattingTests {
@Test @Test
public void testBindISOTime() { public void testBindISOTime() {
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("isoTime", "12:00:00");
binder.bind(propertyValues);
assertEquals(0, binder.getBindingResult().getErrorCount());
assertEquals("12:00:00", binder.getBindingResult().getFieldValue("isoTime"));
}
@Test
public void testBindISOTimeWithZone() {
MutablePropertyValues propertyValues = new MutablePropertyValues(); MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("isoTime", "12:00:00.000-05:00"); propertyValues.add("isoTime", "12:00:00.000-05:00");
binder.bind(propertyValues); binder.bind(propertyValues);
...@@ -320,6 +329,15 @@ public class DateTimeFormattingTests { ...@@ -320,6 +329,15 @@ public class DateTimeFormattingTests {
@Test @Test
public void testBindISODateTime() { public void testBindISODateTime() {
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("isoDateTime", "2009-10-31T12:00:00");
binder.bind(propertyValues);
assertEquals(0, binder.getBindingResult().getErrorCount());
assertEquals("2009-10-31T12:00:00", binder.getBindingResult().getFieldValue("isoDateTime"));
}
@Test
public void testBindISODateTimeWithZone() {
MutablePropertyValues propertyValues = new MutablePropertyValues(); MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("isoDateTime", "2009-10-31T12:00:00.000Z"); propertyValues.add("isoDateTime", "2009-10-31T12:00:00.000Z");
binder.bind(propertyValues); binder.bind(propertyValues);
...@@ -386,29 +404,29 @@ public class DateTimeFormattingTests { ...@@ -386,29 +404,29 @@ public class DateTimeFormattingTests {
private LocalDate localDate; private LocalDate localDate;
@DateTimeFormat(style="M-") @DateTimeFormat(style = "M-")
private LocalDate localDateAnnotated; private LocalDate localDateAnnotated;
private LocalTime localTime; private LocalTime localTime;
@DateTimeFormat(style="-M") @DateTimeFormat(style = "-M")
private LocalTime localTimeAnnotated; private LocalTime localTimeAnnotated;
private LocalDateTime localDateTime; private LocalDateTime localDateTime;
@DateTimeFormat(style="MM") @DateTimeFormat(style = "MM")
private LocalDateTime localDateTimeAnnotated; private LocalDateTime localDateTimeAnnotated;
@DateTimeFormat(pattern="M/d/yy h:mm a") @DateTimeFormat(pattern = "M/d/yy h:mm a")
private LocalDateTime dateTimeAnnotatedPattern; private LocalDateTime dateTimeAnnotatedPattern;
@DateTimeFormat(iso=ISO.DATE) @DateTimeFormat(iso = ISO.DATE)
private LocalDate isoDate; private LocalDate isoDate;
@DateTimeFormat(iso=ISO.TIME) @DateTimeFormat(iso = ISO.TIME)
private LocalTime isoTime; private LocalTime isoTime;
@DateTimeFormat(iso=ISO.DATE_TIME) @DateTimeFormat(iso = ISO.DATE_TIME)
private LocalDateTime isoDateTime; private LocalDateTime isoDateTime;
private Instant instant; private Instant instant;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册