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