提交 6660227d 编写于 作者: P Phillip Webb

Support for custom global Joda DateTimeFormatters

Added dateFormatter, timeFormatter and dateTimeFormatter properties
to JodaTimeFormatterRegistrar allowing for custom global formatting.

DateTimeFormatterFactory can be used when configuring with XML.

Issue: SPR-7121
上级 856fb2cc
...@@ -47,6 +47,7 @@ public class DateFormatterRegistrar implements FormatterRegistrar { ...@@ -47,6 +47,7 @@ public class DateFormatterRegistrar implements FormatterRegistrar {
public void registerFormatters(FormatterRegistry registry) { public void registerFormatters(FormatterRegistry registry) {
addDateConverters(registry); addDateConverters(registry);
registry.addFormatter(dateFormatter); registry.addFormatter(dateFormatter);
registry.addFormatterForFieldType(Calendar.class, dateFormatter);
registry.addFormatterForFieldAnnotation(new DateTimeFormatAnnotationFormatterFactory()); registry.addFormatterForFieldAnnotation(new DateTimeFormatAnnotationFormatterFactory());
} }
......
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.format.datetime.joda;
import java.util.TimeZone;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.format.annotation.DateTimeFormat.ISO;
import org.springframework.util.StringUtils;
/**
* {@link FactoryBean} that creates a Joda {@link DateTimeFormatter}. Formatters will be
* created using the defined {@link #setPattern(String) pattern}, {@link #setIso(ISO) ISO}
* or {@link #setStyle(String) style} (considered in that order).
*
* @author Phillip Webb
* @see #getDateTimeFormatter()
* @see #getDateTimeFormatter(DateTimeFormatter)
* @since 3.2
*/
public class DateTimeFormatterFactory implements FactoryBean<DateTimeFormatter> {
private ISO iso;
private String style;
private String pattern;
private TimeZone timeZone;
/**
* Create a new {@link DateTimeFormatterFactory} instance.
*/
public DateTimeFormatterFactory() {
}
/**
* Create a new {@link DateTimeFormatterFactory} instance.
* @param pattern the pattern to use to format date values
*/
public DateTimeFormatterFactory(String pattern) {
this.pattern = pattern;
}
public boolean isSingleton() {
return true;
}
public Class<?> getObjectType() {
return DateTimeFormatter.class;
}
public DateTimeFormatter getObject() throws Exception {
return getDateTimeFormatter();
}
/**
* Get a new DateTimeFormatter using this factory. If no specific
* {@link #setStyle(String) style} {@link #setIso(ISO) ISO} or
* {@link #setPattern(String) pattern} have been defined the
* {@link DateTimeFormat#mediumDateTime() medium date time format} will be used.
* @return a new date time formatter
* @see #getObject()
* @see #getDateTimeFormatter(DateTimeFormatter)
*/
public DateTimeFormatter getDateTimeFormatter() {
return getDateTimeFormatter(DateTimeFormat.mediumDateTime());
}
/**
* Get a new DateTimeFormatter using this factory. If no specific
* {@link #setStyle(String) style} {@link #setIso(ISO) ISO} or
* {@link #setPattern(String) pattern} have been defined the specific
* {@code fallbackFormatter} will be used.
* @param fallbackFormatter the fall-back formatter to use when no specific factory
* properties have been set (can be {@code null}).
* @return a new date time formatter
*/
public DateTimeFormatter getDateTimeFormatter(DateTimeFormatter fallbackFormatter) {
DateTimeFormatter dateTimeFormatter = createDateTimeFormatter();
if(dateTimeFormatter != null && this.timeZone != null) {
dateTimeFormatter.withZone(DateTimeZone.forTimeZone(this.timeZone));
}
return (dateTimeFormatter != null ? dateTimeFormatter : fallbackFormatter);
}
private DateTimeFormatter createDateTimeFormatter() {
if (StringUtils.hasLength(pattern)) {
return DateTimeFormat.forPattern(pattern);
}
if (iso != null && iso != ISO.NONE) {
if (iso == ISO.DATE) {
return ISODateTimeFormat.date();
}
if (iso == ISO.TIME) {
return ISODateTimeFormat.time();
}
return ISODateTimeFormat.dateTime();
}
if (StringUtils.hasLength(style)) {
return DateTimeFormat.forStyle(style);
}
return null;
}
/**
* Set the TimeZone to normalize the date values into, if any.
* @param timeZone the time zone
*/
public void setTimeZone(TimeZone timeZone) {
this.timeZone = timeZone;
}
/**
* Set the two character to use to format date values. The first character used for
* the date style, the second is for the time style. Supported characters are
* <ul>
* <li>'S' = Small</li>
* <li>'M' = Medium</li>
* <li>'L' = Long</li>
* <li>'F' = Full</li>
* <li>'-' = Omitted</li>
* <ul>
* This method mimics the styles supported by Joda Time.
* @param style two characters from the set {"S", "M", "L", "F", "-"}
*/
public void setStyle(String style) {
this.style = style;
}
/**
* Set the ISO format used for this date.
* @param iso the iso format
*/
public void setIso(ISO iso) {
this.iso = iso;
}
/**
* Set the pattern to use to format date values.
* @param pattern the format pattern
*/
public void setPattern(String pattern) {
this.pattern = pattern;
}
}
...@@ -34,8 +34,6 @@ import org.springframework.format.AnnotationFormatterFactory; ...@@ -34,8 +34,6 @@ import org.springframework.format.AnnotationFormatterFactory;
import org.springframework.format.Parser; import org.springframework.format.Parser;
import org.springframework.format.Printer; import org.springframework.format.Printer;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.DateTimeFormat.ISO;
import org.springframework.util.StringUtils;
import org.springframework.util.StringValueResolver; import org.springframework.util.StringValueResolver;
/** /**
...@@ -49,18 +47,31 @@ import org.springframework.util.StringValueResolver; ...@@ -49,18 +47,31 @@ import org.springframework.util.StringValueResolver;
public class JodaDateTimeFormatAnnotationFormatterFactory public class JodaDateTimeFormatAnnotationFormatterFactory
implements AnnotationFormatterFactory<DateTimeFormat>, EmbeddedValueResolverAware { implements AnnotationFormatterFactory<DateTimeFormat>, EmbeddedValueResolverAware {
private final Set<Class<?>> fieldTypes; private static final Set<Class<?>> FIELD_TYPES;
static {
private StringValueResolver embeddedValueResolver; // Create the set of field types that may be annotated with @DateTimeFormat.
// Note: the 3 ReadablePartial concrete types are registered explicitly since
// addFormatterForFieldType rules exist for each of these types
// (if we did not do this, the default byType rules for LocalDate, LocalTime,
// and LocalDateTime would take precedence over the annotation rule, which
// is not what we want)
Set<Class<?>> fieldTypes = new HashSet<Class<?>>(7);
fieldTypes.add(ReadableInstant.class);
fieldTypes.add(LocalDate.class);
fieldTypes.add(LocalTime.class);
fieldTypes.add(LocalDateTime.class);
fieldTypes.add(Date.class);
fieldTypes.add(Calendar.class);
fieldTypes.add(Long.class);
FIELD_TYPES = Collections.unmodifiableSet(fieldTypes);
}
public JodaDateTimeFormatAnnotationFormatterFactory() { private StringValueResolver embeddedValueResolver;
this.fieldTypes = createFieldTypes();
}
public final Set<Class<?>> getFieldTypes() { public final Set<Class<?>> getFieldTypes() {
return this.fieldTypes; return FIELD_TYPES;
} }
public void setEmbeddedValueResolver(StringValueResolver resolver) { public void setEmbeddedValueResolver(StringValueResolver resolver) {
...@@ -72,77 +83,41 @@ public class JodaDateTimeFormatAnnotationFormatterFactory ...@@ -72,77 +83,41 @@ public class JodaDateTimeFormatAnnotationFormatterFactory
} }
public Printer<?> getPrinter(DateTimeFormat annotation, Class<?> fieldType) { public Printer<?> getPrinter(DateTimeFormat annotation, Class<?> fieldType) {
DateTimeFormatter formatter = configureDateTimeFormatterFrom(annotation); DateTimeFormatter formatter = getFormatter(annotation, fieldType);
if (ReadableInstant.class.isAssignableFrom(fieldType)) { if (ReadableInstant.class.isAssignableFrom(fieldType)) {
return new ReadableInstantPrinter(formatter); return new ReadableInstantPrinter(formatter);
} }
else if (ReadablePartial.class.isAssignableFrom(fieldType)) {
if (ReadablePartial.class.isAssignableFrom(fieldType)) {
return new ReadablePartialPrinter(formatter); return new ReadablePartialPrinter(formatter);
} }
else if (Calendar.class.isAssignableFrom(fieldType)) {
if (Calendar.class.isAssignableFrom(fieldType)) {
// assumes Calendar->ReadableInstant converter is registered // assumes Calendar->ReadableInstant converter is registered
return new ReadableInstantPrinter(formatter); return new ReadableInstantPrinter(formatter);
} }
else {
// assumes Date->Long converter is registered // assumes Date->Long converter is registered
return new MillisecondInstantPrinter(formatter); return new MillisecondInstantPrinter(formatter);
}
} }
public Parser<DateTime> getParser(DateTimeFormat annotation, Class<?> fieldType) { public Parser<DateTime> getParser(DateTimeFormat annotation, Class<?> fieldType) {
return new DateTimeParser(configureDateTimeFormatterFrom(annotation)); return new DateTimeParser(getFormatter(annotation, fieldType));
} }
// internal helpers
/** /**
* Create the set of field types that may be annotated with @DateTimeFormat. * Factory method used to create a {@link DateTimeFormatter}.
* Note: the 3 ReadablePartial concrete types are registered explicitly since addFormatterForFieldType rules exist for each of these types * @param annotation the format annotation for the field
* (if we did not do this, the default byType rules for LocalDate, LocalTime, and LocalDateTime would take precedence over the annotation rule, which is not what we want) * @param fieldType the type of field
* @see JodaTimeFormatterRegistrar#registerFormatters(org.springframework.format.FormatterRegistry) * @return a {@link DateTimeFormatter} instance
* @since 3.2
*/ */
private Set<Class<?>> createFieldTypes() { protected DateTimeFormatter getFormatter(DateTimeFormat annotation, Class<?> fieldType) {
Set<Class<?>> rawFieldTypes = new HashSet<Class<?>>(7); DateTimeFormatterFactory factory = new DateTimeFormatterFactory();
rawFieldTypes.add(ReadableInstant.class); factory.setStyle(resolveEmbeddedValue(annotation.style()));
rawFieldTypes.add(LocalDate.class); factory.setIso(annotation.iso());
rawFieldTypes.add(LocalTime.class); factory.setPattern(resolveEmbeddedValue(annotation.pattern()));
rawFieldTypes.add(LocalDateTime.class); return factory.getDateTimeFormatter();
rawFieldTypes.add(Date.class);
rawFieldTypes.add(Calendar.class);
rawFieldTypes.add(Long.class);
return Collections.unmodifiableSet(rawFieldTypes);
}
private DateTimeFormatter configureDateTimeFormatterFrom(DateTimeFormat annotation) {
if (StringUtils.hasLength(annotation.pattern())) {
return forPattern(resolveEmbeddedValue(annotation.pattern()));
}
else if (annotation.iso() != ISO.NONE) {
return forIso(annotation.iso());
}
else {
return forStyle(resolveEmbeddedValue(annotation.style()));
}
}
private DateTimeFormatter forPattern(String pattern) {
return org.joda.time.format.DateTimeFormat.forPattern(pattern);
}
private DateTimeFormatter forStyle(String style) {
return org.joda.time.format.DateTimeFormat.forStyle(style);
} }
private DateTimeFormatter forIso(ISO iso) {
if (iso == ISO.DATE) {
return org.joda.time.format.ISODateTimeFormat.date();
}
else if (iso == ISO.TIME) {
return org.joda.time.format.ISODateTimeFormat.time();
}
else {
return org.joda.time.format.ISODateTimeFormat.dateTime();
}
}
} }
...@@ -17,6 +17,8 @@ package org.springframework.format.datetime.joda; ...@@ -17,6 +17,8 @@ package org.springframework.format.datetime.joda;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
...@@ -25,17 +27,19 @@ import org.joda.time.LocalTime; ...@@ -25,17 +27,19 @@ import org.joda.time.LocalTime;
import org.joda.time.ReadableInstant; import org.joda.time.ReadableInstant;
import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter; import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
import org.springframework.format.FormatterRegistrar; import org.springframework.format.FormatterRegistrar;
import org.springframework.format.FormatterRegistry; import org.springframework.format.FormatterRegistry;
import org.springframework.format.Parser; import org.springframework.format.Parser;
import org.springframework.format.Printer; import org.springframework.format.Printer;
import org.springframework.format.annotation.DateTimeFormat.ISO;
import org.springframework.format.datetime.DateFormatterRegistrar;
/** /**
* Configures Joda Time's Formatting system for use with Spring. * Configures Joda Time's Formatting system for use with Spring.
* *
* @author Keith Donald * @author Keith Donald
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Phillip Webb
* @since 3.1 * @since 3.1
* @see #setDateStyle * @see #setDateStyle
* @see #setTimeStyle * @see #setTimeStyle
...@@ -46,20 +50,31 @@ import org.springframework.format.Printer; ...@@ -46,20 +50,31 @@ import org.springframework.format.Printer;
*/ */
public class JodaTimeFormatterRegistrar implements FormatterRegistrar { public class JodaTimeFormatterRegistrar implements FormatterRegistrar {
private String dateStyle; /**
* User defined formatters.
*/
private Map<Type, DateTimeFormatter> formatters = new HashMap<Type, DateTimeFormatter>();
/**
* Factories used when specific formatters have not been specified.
*/
private Map<Type, DateTimeFormatterFactory> factories;
private String timeStyle;
private String dateTimeStyle; public JodaTimeFormatterRegistrar() {
this.factories = new HashMap<Type, DateTimeFormatterFactory>();
for (Type type : Type.values()) {
this.factories.put(type, new DateTimeFormatterFactory());
}
}
private boolean useIsoFormat;
/** /**
* Set the default format style of Joda {@link LocalDate} objects. * Set the default format style of Joda {@link LocalDate} objects.
* Default is {@link DateTimeFormat#shortDate()}. * Default is {@link DateTimeFormat#shortDate()}.
*/ */
public void setDateStyle(String dateStyle) { public void setDateStyle(String dateStyle) {
this.dateStyle = dateStyle; factories.get(Type.DATE).setStyle(dateStyle+"-");
} }
/** /**
...@@ -67,7 +82,7 @@ public class JodaTimeFormatterRegistrar implements FormatterRegistrar { ...@@ -67,7 +82,7 @@ public class JodaTimeFormatterRegistrar implements FormatterRegistrar {
* Default is {@link DateTimeFormat#shortTime()}. * Default is {@link DateTimeFormat#shortTime()}.
*/ */
public void setTimeStyle(String timeStyle) { public void setTimeStyle(String timeStyle) {
this.timeStyle = timeStyle; factories.get(Type.TIME).setStyle("-"+timeStyle);
} }
/** /**
...@@ -76,7 +91,7 @@ public class JodaTimeFormatterRegistrar implements FormatterRegistrar { ...@@ -76,7 +91,7 @@ public class JodaTimeFormatterRegistrar implements FormatterRegistrar {
* Default is {@link DateTimeFormat#shortDateTime()}. * Default is {@link DateTimeFormat#shortDateTime()}.
*/ */
public void setDateTimeStyle(String dateTimeStyle) { public void setDateTimeStyle(String dateTimeStyle) {
this.dateTimeStyle = dateTimeStyle; factories.get(Type.DATE_TIME).setStyle(dateTimeStyle);
} }
/** /**
...@@ -85,64 +100,108 @@ public class JodaTimeFormatterRegistrar implements FormatterRegistrar { ...@@ -85,64 +100,108 @@ public class JodaTimeFormatterRegistrar implements FormatterRegistrar {
* If set to true, the dateStyle, timeStyle, and dateTimeStyle properties are ignored. * If set to true, the dateStyle, timeStyle, and dateTimeStyle properties are ignored.
*/ */
public void setUseIsoFormat(boolean useIsoFormat) { public void setUseIsoFormat(boolean useIsoFormat) {
this.useIsoFormat = useIsoFormat; factories.get(Type.DATE).setIso(useIsoFormat ? ISO.DATE : null);
factories.get(Type.TIME).setIso(useIsoFormat ? ISO.TIME : null);
factories.get(Type.DATE_TIME).setIso(useIsoFormat ? ISO.DATE_TIME : null);
}
/**
* Set the formatter that will be used for objects representing date values.
* This formatter will be used for the {@link LocalDate} type. When specified
* {@link #setDateStyle(String) dateStyle} and
* {@link #setUseIsoFormat(boolean) useIsoFormat} properties will be ignored.
* @param formatter the formatter to use
* @see #setTimeFormatter(DateTimeFormatter)
* @see #setDateTimeFormatter(DateTimeFormatter)
* @since 3.2
*/
public void setDateFormatter(DateTimeFormatter formatter) {
this.formatters.put(Type.DATE, formatter);
}
/**
* Set the formatter that will be used for objects representing date values.
* This formatter will be used for the {@link LocalTime} type. When specified
* {@link #setTimeStyle(String) timeStyle} and
* {@link #setUseIsoFormat(boolean) useIsoFormat} properties will be ignored.
* @param formatter the formatter to use
* @see #setDateFormatter(DateTimeFormatter)
* @see #setDateTimeFormatter(DateTimeFormatter)
* @since 3.2
*/
public void setTimeFormatter(DateTimeFormatter formatter) {
this.formatters.put(Type.TIME, formatter);
}
/**
* Set the formatter that will be used for objects representing date and time values.
* This formatter will be used for {@link LocalDateTime}, {@link ReadableInstant},
* {@link Date} and {@link Calendar} types. When specified
* {@link #setDateTimeStyle(String) dateTimeStyle} and
* {@link #setUseIsoFormat(boolean) useIsoFormat} properties will be ignored.
* @param formatter the formatter to use
* @see #setDateFormatter(DateTimeFormatter)
* @see #setTimeFormatter(DateTimeFormatter)
* @since 3.2
*/
public void setDateTimeFormatter(DateTimeFormatter formatter) {
this.formatters.put(Type.DATE_TIME, formatter);
} }
public void registerFormatters(FormatterRegistry registry) { public void registerFormatters(FormatterRegistry registry) {
JodaTimeConverters.registerConverters(registry); JodaTimeConverters.registerConverters(registry);
DateTimeFormatter jodaDateFormatter = getJodaDateFormatter(); DateTimeFormatter dateFormatter = getFormatter(Type.DATE);
registry.addFormatterForFieldType(LocalDate.class, new ReadablePartialPrinter(jodaDateFormatter), DateTimeFormatter timeFormatter = getFormatter(Type.TIME);
new DateTimeParser(jodaDateFormatter)); DateTimeFormatter dateTimeFormatter = getFormatter(Type.DATE_TIME);
DateTimeFormatter jodaTimeFormatter = getJodaTimeFormatter(); addFormatterForFields(registry,
registry.addFormatterForFieldType(LocalTime.class, new ReadablePartialPrinter(jodaTimeFormatter), new ReadablePartialPrinter(dateFormatter),
new DateTimeParser(jodaTimeFormatter)); new DateTimeParser(dateFormatter),
LocalDate.class);
DateTimeFormatter jodaDateTimeFormatter = getJodaDateTimeFormatter(); addFormatterForFields(registry,
Parser<DateTime> dateTimeParser = new DateTimeParser(jodaDateTimeFormatter); new ReadablePartialPrinter(timeFormatter),
registry.addFormatterForFieldType(LocalDateTime.class, new ReadablePartialPrinter(jodaDateTimeFormatter), new DateTimeParser(timeFormatter),
dateTimeParser); LocalTime.class);
Printer<ReadableInstant> readableInstantPrinter = new ReadableInstantPrinter(jodaDateTimeFormatter); addFormatterForFields(registry,
registry.addFormatterForFieldType(ReadableInstant.class, readableInstantPrinter, dateTimeParser); new ReadablePartialPrinter(dateTimeFormatter),
new DateTimeParser(dateTimeFormatter),
LocalDateTime.class);
registry.addFormatterForFieldAnnotation(new JodaDateTimeFormatAnnotationFormatterFactory()); addFormatterForFields(registry,
} new ReadableInstantPrinter(dateTimeFormatter),
new DateTimeParser(dateTimeFormatter),
ReadableInstant.class, Date.class, Calendar.class);
// internal helpers registry.addFormatterForFieldAnnotation(
new JodaDateTimeFormatAnnotationFormatterFactory());
}
private DateTimeFormatter getJodaDateFormatter() { private DateTimeFormatter getFormatter(Type type) {
if (this.useIsoFormat) { DateTimeFormatter formatter = formatters.get(type);
return ISODateTimeFormat.date(); if(formatter != null) {
} return formatter;
if (this.dateStyle != null) {
return DateTimeFormat.forStyle(this.dateStyle + "-");
} else {
return DateTimeFormat.shortDate();
} }
DateTimeFormatter fallbackFormatter = getFallbackFormatter(type);
return factories.get(type).getDateTimeFormatter(fallbackFormatter );
} }
private DateTimeFormatter getJodaTimeFormatter() { private DateTimeFormatter getFallbackFormatter(Type type) {
if (this.useIsoFormat) { switch (type) {
return ISODateTimeFormat.time(); case DATE: return DateTimeFormat.shortDate();
} case TIME: return DateTimeFormat.shortTime();
if (this.timeStyle != null) { default: return DateTimeFormat.shortDateTime();
return DateTimeFormat.forStyle("-" + this.timeStyle);
} else {
return DateTimeFormat.shortTime();
} }
} }
private DateTimeFormatter getJodaDateTimeFormatter() { private void addFormatterForFields(FormatterRegistry registry, Printer<?> printer,
if (this.useIsoFormat) { Parser<?> parser, Class<?>... fieldTypes) {
return ISODateTimeFormat.dateTime(); for (Class<?> fieldType : fieldTypes) {
} registry.addFormatterForFieldType(fieldType, printer, parser);
if (this.dateTimeStyle != null) {
return DateTimeFormat.forStyle(this.dateTimeStyle);
} else {
return DateTimeFormat.shortDateTime();
} }
} }
private static enum Type {DATE, TIME, DATE_TIME}
} }
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.format.datetime.joda;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.Matchers.sameInstance;
import static org.junit.Assert.*;
import java.util.Locale;
import java.util.TimeZone;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.junit.Test;
import org.springframework.format.annotation.DateTimeFormat.ISO;
/**
* Tests for {@link DateTimeFormatterFactory}.
*
* @author Phillip Webb
*/
public class DateTimeFormatterFactoryTests {
private DateTimeFormatterFactory factory = new DateTimeFormatterFactory();
private DateTime dateTime = new DateTime(2009, 10, 21, 12, 10, 00, 00);
@Test
public void shouldDefaultToMediumFormat() throws Exception {
assertThat(factory.getObject(), is(equalTo(DateTimeFormat.mediumDateTime())));
assertThat(factory.getDateTimeFormatter(), is(equalTo(DateTimeFormat.mediumDateTime())));
}
@Test
public void shouldCreateFromPattern() throws Exception {
factory = new DateTimeFormatterFactory("yyyyMMddHHmmss");
DateTimeFormatter formatter = factory.getObject();
assertThat(formatter.print(dateTime), is("20091021121000"));
}
@Test
public void shouldBeSingleton() throws Exception {
assertThat(factory.isSingleton(), is(true));
}
@Test
@SuppressWarnings("rawtypes")
public void shouldCreateDateTimeFormatter() throws Exception {
assertThat(factory.getObjectType(), is(equalTo((Class)DateTimeFormatter.class)));
}
@Test
public void shouldGetDateTimeFormatterNullFallback() throws Exception {
DateTimeFormatter formatter = factory.getDateTimeFormatter(null);
assertThat(formatter, is(nullValue()));
}
@Test
public void shouldGetDateTimeFormatterFallback() throws Exception {
DateTimeFormatter fallback = DateTimeFormat.forStyle("LL");
DateTimeFormatter formatter = factory.getDateTimeFormatter(fallback);
assertThat(formatter, is(sameInstance(fallback)));
}
@Test
public void shouldGetDateTimeFormatter() throws Exception {
factory.setStyle("SS");
assertThat(applyLocale(factory.getDateTimeFormatter()).print(dateTime), is("10/21/09 12:10 PM"));
factory.setIso(ISO.DATE);
assertThat(applyLocale(factory.getDateTimeFormatter()).print(dateTime), is("2009-10-21"));
factory.setPattern("yyyyMMddHHmmss");
assertThat(factory.getDateTimeFormatter().print(dateTime), is("20091021121000"));
}
@Test
public void shouldGetWithTimeZone() throws Exception {
factory.setPattern("yyyyMMddHHmmss Z");
factory.setTimeZone(TimeZone.getTimeZone("-0700"));
assertThat(factory.getDateTimeFormatter().print(dateTime), is("20091021121000 -0700"));
}
private DateTimeFormatter applyLocale(DateTimeFormatter dateTimeFormatter) {
return dateTimeFormatter.withLocale(Locale.US);
}
}
...@@ -49,15 +49,20 @@ import static org.junit.Assert.*; ...@@ -49,15 +49,20 @@ import static org.junit.Assert.*;
*/ */
public class JodaTimeFormattingTests { public class JodaTimeFormattingTests {
private FormattingConversionService conversionService = new FormattingConversionService(); private FormattingConversionService conversionService;
private DataBinder binder; private DataBinder binder;
@Before @Before
public void setUp() { public void setUp() {
JodaTimeFormatterRegistrar registrar = new JodaTimeFormatterRegistrar();
setUp(registrar);
}
private void setUp(JodaTimeFormatterRegistrar registrar) {
conversionService = new FormattingConversionService();
DefaultConversionService.addDefaultConverters(conversionService); DefaultConversionService.addDefaultConverters(conversionService);
JodaTimeFormatterRegistrar registrar = new JodaTimeFormatterRegistrar();
registrar.registerFormatters(conversionService); registrar.registerFormatters(conversionService);
JodaTimeBean bean = new JodaTimeBean(); JodaTimeBean bean = new JodaTimeBean();
...@@ -84,7 +89,7 @@ public class JodaTimeFormattingTests { ...@@ -84,7 +89,7 @@ public class JodaTimeFormattingTests {
System.out.println(org.joda.time.format.DateTimeFormat.patternForStyle("LL", LocaleContextHolder.getLocale())); System.out.println(org.joda.time.format.DateTimeFormat.patternForStyle("LL", LocaleContextHolder.getLocale()));
System.out.println(org.joda.time.format.DateTimeFormat.patternForStyle("FF", LocaleContextHolder.getLocale())); System.out.println(org.joda.time.format.DateTimeFormat.patternForStyle("FF", LocaleContextHolder.getLocale()));
} }
@Test @Test
public void testBindLocalDate() { public void testBindLocalDate() {
MutablePropertyValues propertyValues = new MutablePropertyValues(); MutablePropertyValues propertyValues = new MutablePropertyValues();
...@@ -94,6 +99,30 @@ public class JodaTimeFormattingTests { ...@@ -94,6 +99,30 @@ public class JodaTimeFormattingTests {
assertEquals("10/31/09", binder.getBindingResult().getFieldValue("localDate")); assertEquals("10/31/09", binder.getBindingResult().getFieldValue("localDate"));
} }
@Test
public void testBindLocalDateWithSpecificStyle() throws Exception {
JodaTimeFormatterRegistrar registrar = new JodaTimeFormatterRegistrar();
registrar.setDateStyle("L");
setUp(registrar);
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("localDate", "October 31, 2009");
binder.bind(propertyValues);
assertEquals(0, binder.getBindingResult().getErrorCount());
assertEquals("October 31, 2009", binder.getBindingResult().getFieldValue("localDate"));
}
@Test
public void testBindLocalDateWithSpecifcFormatter() throws Exception {
JodaTimeFormatterRegistrar registrar = new JodaTimeFormatterRegistrar();
registrar.setDateFormatter(org.joda.time.format.DateTimeFormat.forPattern("yyyyMMdd"));
setUp(registrar);
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("localDate", "20091031");
binder.bind(propertyValues);
assertEquals(0, binder.getBindingResult().getErrorCount());
assertEquals("20091031", binder.getBindingResult().getFieldValue("localDate"));
}
@Test @Test
public void testBindLocalDateArray() { public void testBindLocalDateArray() {
MutablePropertyValues propertyValues = new MutablePropertyValues(); MutablePropertyValues propertyValues = new MutablePropertyValues();
...@@ -158,6 +187,30 @@ public class JodaTimeFormattingTests { ...@@ -158,6 +187,30 @@ public class JodaTimeFormattingTests {
assertEquals("12:00 PM", binder.getBindingResult().getFieldValue("localTime")); assertEquals("12:00 PM", binder.getBindingResult().getFieldValue("localTime"));
} }
@Test
public void testBindLocalTimeWithSpecificStyle() throws Exception {
JodaTimeFormatterRegistrar registrar = new JodaTimeFormatterRegistrar();
registrar.setTimeStyle("M");
setUp(registrar);
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("localTime", "12:00:00 PM");
binder.bind(propertyValues);
assertEquals(0, binder.getBindingResult().getErrorCount());
assertEquals("12:00:00 PM", binder.getBindingResult().getFieldValue("localTime"));
}
@Test
public void testBindLocalTimeWithSpecificFormatter() throws Exception {
JodaTimeFormatterRegistrar registrar = new JodaTimeFormatterRegistrar();
registrar.setTimeFormatter(org.joda.time.format.DateTimeFormat.forPattern("HHmmss"));
setUp(registrar);
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("localTime", "130000");
binder.bind(propertyValues);
assertEquals(0, binder.getBindingResult().getErrorCount());
assertEquals("130000", binder.getBindingResult().getFieldValue("localTime"));
}
@Test @Test
public void testBindLocalTimeAnnotated() { public void testBindLocalTimeAnnotated() {
MutablePropertyValues propertyValues = new MutablePropertyValues(); MutablePropertyValues propertyValues = new MutablePropertyValues();
...@@ -205,6 +258,42 @@ public class JodaTimeFormattingTests { ...@@ -205,6 +258,42 @@ public class JodaTimeFormattingTests {
assertEquals("10/31/09 12:00 PM", binder.getBindingResult().getFieldValue("dateTime")); assertEquals("10/31/09 12:00 PM", binder.getBindingResult().getFieldValue("dateTime"));
} }
@Test
public void testBindDateTimeWithSpecificStyle() throws Exception {
JodaTimeFormatterRegistrar registrar = new JodaTimeFormatterRegistrar();
registrar.setDateTimeStyle("MM");
setUp(registrar);
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("localDateTime", "Oct 31, 2009 12:00:00 PM");
binder.bind(propertyValues);
assertEquals(0, binder.getBindingResult().getErrorCount());
assertEquals("Oct 31, 2009 12:00:00 PM", binder.getBindingResult().getFieldValue("localDateTime"));
}
@Test
public void testBindDateTimeISO() throws Exception {
JodaTimeFormatterRegistrar registrar = new JodaTimeFormatterRegistrar();
registrar.setUseIsoFormat(true);
setUp(registrar);
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("dateTime", "2009-10-31T12:00:00.000Z");
binder.bind(propertyValues);
assertEquals(0, binder.getBindingResult().getErrorCount());
assertEquals("2009-10-31T07:00:00.000-05:00", binder.getBindingResult().getFieldValue("dateTime"));
}
@Test
public void testBindDateTimeWithSpecificFormatter() throws Exception {
JodaTimeFormatterRegistrar registrar = new JodaTimeFormatterRegistrar();
registrar.setDateTimeFormatter(org.joda.time.format.DateTimeFormat.forPattern("yyyyMMddHHmmss"));
setUp(registrar);
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("dateTime", "20091031130000");
binder.bind(propertyValues);
assertEquals(0, binder.getBindingResult().getErrorCount());
assertEquals("20091031130000", binder.getBindingResult().getFieldValue("dateTime"));
}
@Test @Test
public void testBindDateTimeAnnotated() { public void testBindDateTimeAnnotated() {
MutablePropertyValues propertyValues = new MutablePropertyValues(); MutablePropertyValues propertyValues = new MutablePropertyValues();
...@@ -339,7 +428,7 @@ public class JodaTimeFormattingTests { ...@@ -339,7 +428,7 @@ public class JodaTimeFormattingTests {
assertEquals(0, binder.getBindingResult().getErrorCount()); assertEquals(0, binder.getBindingResult().getErrorCount());
assertEquals("10/31/09 12:00 PM", binder.getBindingResult().getFieldValue("instant")); assertEquals("10/31/09 12:00 PM", binder.getBindingResult().getFieldValue("instant"));
} }
@Test @Test
public void testBindInstantAnnotated() { public void testBindInstantAnnotated() {
MutablePropertyValues propertyValues = new MutablePropertyValues(); MutablePropertyValues propertyValues = new MutablePropertyValues();
...@@ -357,7 +446,7 @@ public class JodaTimeFormattingTests { ...@@ -357,7 +446,7 @@ public class JodaTimeFormattingTests {
assertEquals(0, binder.getBindingResult().getErrorCount()); assertEquals(0, binder.getBindingResult().getErrorCount());
assertEquals("10/31/09 12:00 PM", binder.getBindingResult().getFieldValue("mutableDateTime")); assertEquals("10/31/09 12:00 PM", binder.getBindingResult().getFieldValue("mutableDateTime"));
} }
@Test @Test
public void testBindMutableDateTimeAnnotated() { public void testBindMutableDateTimeAnnotated() {
MutablePropertyValues propertyValues = new MutablePropertyValues(); MutablePropertyValues propertyValues = new MutablePropertyValues();
...@@ -483,7 +572,7 @@ public class JodaTimeFormattingTests { ...@@ -483,7 +572,7 @@ public class JodaTimeFormattingTests {
public void setLocalDateTimeAnnotated(LocalDateTime localDateTimeAnnotated) { public void setLocalDateTimeAnnotated(LocalDateTime localDateTimeAnnotated) {
this.localDateTimeAnnotated = localDateTimeAnnotated; this.localDateTimeAnnotated = localDateTimeAnnotated;
} }
public LocalDateTime getLocalDateTimeAnnotatedLong() { public LocalDateTime getLocalDateTimeAnnotatedLong() {
return localDateTimeAnnotatedLong; return localDateTimeAnnotatedLong;
} }
...@@ -596,7 +685,7 @@ public class JodaTimeFormattingTests { ...@@ -596,7 +685,7 @@ public class JodaTimeFormattingTests {
public void setIsoDateTime(DateTime isoDateTime) { public void setIsoDateTime(DateTime isoDateTime) {
this.isoDateTime = isoDateTime; this.isoDateTime = isoDateTime;
} }
public Instant getInstant() { public Instant getInstant() {
return instant; return instant;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册