From a75b6ee5b61fba7387fba8d7dfb696de7e271e00 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Sun, 30 Sep 2012 09:56:43 -0700 Subject: [PATCH 1/5] Polish whitespace and formatting --- .../format/annotation/DateTimeFormat.java | 10 ++-- ...eTimeFormatAnnotationFormatterFactory.java | 21 ++++--- .../datetime/joda/JodaTimeConverters.java | 56 +++++++++---------- 3 files changed, 43 insertions(+), 44 deletions(-) diff --git a/spring-context/src/main/java/org/springframework/format/annotation/DateTimeFormat.java b/spring-context/src/main/java/org/springframework/format/annotation/DateTimeFormat.java index 8646fa3415..b09483274c 100644 --- a/spring-context/src/main/java/org/springframework/format/annotation/DateTimeFormat.java +++ b/spring-context/src/main/java/org/springframework/format/annotation/DateTimeFormat.java @@ -26,7 +26,7 @@ import java.lang.annotation.Target; * Supports formatting by style pattern, ISO date time pattern, or custom format pattern string. * Can be applied to java.util.Date, java.util.Calendar, java.long.Long, or Joda Time fields. *

- * For style-based formatting, set the {@link #style()} attribute to be the style pattern code. + * For style-based formatting, set the {@link #style()} attribute to be the style pattern code. * The first character of the code is the date style, and the second character is the time style. * Specify a character of 'S' for short style, 'M' for medium, 'L' for long, and 'F' for full. * A date or time may be omitted by specifying the style character '-'. @@ -39,7 +39,7 @@ import java.lang.annotation.Target; * When the pattern attribute is specified, it takes precedence over both the style and ISO attribute. * When the iso attribute is specified, if takes precedence over the style attribute. * When no annotation attributes are specified, the default format applied is style-based with a style code of 'SS' (short date, short time). - * + * * @author Keith Donald * @author Juergen Hoeller * @since 3.0 @@ -76,8 +76,8 @@ public @interface DateTimeFormat { * Common ISO date time format patterns. */ public enum ISO { - - /** + + /** * The most common ISO Date Format yyyy-MM-dd e.g. 2000-10-31. */ DATE, @@ -92,7 +92,7 @@ public @interface DateTimeFormat { * The default if no annotation value is specified. */ DATE_TIME, - + /** * Indicates that no ISO-based format pattern should be applied. */ diff --git a/spring-context/src/main/java/org/springframework/format/datetime/joda/JodaDateTimeFormatAnnotationFormatterFactory.java b/spring-context/src/main/java/org/springframework/format/datetime/joda/JodaDateTimeFormatAnnotationFormatterFactory.java index ad8bbb5beb..a95745884d 100644 --- a/spring-context/src/main/java/org/springframework/format/datetime/joda/JodaDateTimeFormatAnnotationFormatterFactory.java +++ b/spring-context/src/main/java/org/springframework/format/datetime/joda/JodaDateTimeFormatAnnotationFormatterFactory.java @@ -52,17 +52,17 @@ public class JodaDateTimeFormatAnnotationFormatterFactory private final Set> fieldTypes; private StringValueResolver embeddedValueResolver; - + public JodaDateTimeFormatAnnotationFormatterFactory() { this.fieldTypes = createFieldTypes(); } + public final Set> getFieldTypes() { return this.fieldTypes; } - public void setEmbeddedValueResolver(StringValueResolver resolver) { this.embeddedValueResolver = resolver; } @@ -71,9 +71,8 @@ public class JodaDateTimeFormatAnnotationFormatterFactory return (this.embeddedValueResolver != null ? this.embeddedValueResolver.resolveStringValue(value) : value); } - public Printer getPrinter(DateTimeFormat annotation, Class fieldType) { - DateTimeFormatter formatter = configureDateTimeFormatterFrom(annotation); + DateTimeFormatter formatter = configureDateTimeFormatterFrom(annotation); if (ReadableInstant.class.isAssignableFrom(fieldType)) { return new ReadableInstantPrinter(formatter); } @@ -82,21 +81,21 @@ public class JodaDateTimeFormatAnnotationFormatterFactory } else if (Calendar.class.isAssignableFrom(fieldType)) { // assumes Calendar->ReadableInstant converter is registered - return new ReadableInstantPrinter(formatter); + return new ReadableInstantPrinter(formatter); } else { // assumes Date->Long converter is registered return new MillisecondInstantPrinter(formatter); - } + } } public Parser getParser(DateTimeFormat annotation, Class fieldType) { - return new DateTimeParser(configureDateTimeFormatterFrom(annotation)); + return new DateTimeParser(configureDateTimeFormatterFrom(annotation)); } // internal helpers - /** + /** * 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) @@ -111,9 +110,9 @@ public class JodaDateTimeFormatAnnotationFormatterFactory rawFieldTypes.add(Date.class); rawFieldTypes.add(Calendar.class); rawFieldTypes.add(Long.class); - return Collections.unmodifiableSet(rawFieldTypes); + return Collections.unmodifiableSet(rawFieldTypes); } - + private DateTimeFormatter configureDateTimeFormatterFrom(DateTimeFormat annotation) { if (StringUtils.hasLength(annotation.pattern())) { return forPattern(resolveEmbeddedValue(annotation.pattern())); @@ -143,7 +142,7 @@ public class JodaDateTimeFormatAnnotationFormatterFactory } else { return org.joda.time.format.ISODateTimeFormat.dateTime(); - } + } } } diff --git a/spring-context/src/main/java/org/springframework/format/datetime/joda/JodaTimeConverters.java b/spring-context/src/main/java/org/springframework/format/datetime/joda/JodaTimeConverters.java index 05fc3c03db..e7d7118fb6 100644 --- a/spring-context/src/main/java/org/springframework/format/datetime/joda/JodaTimeConverters.java +++ b/spring-context/src/main/java/org/springframework/format/datetime/joda/JodaTimeConverters.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * 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. @@ -59,7 +59,7 @@ final class JodaTimeConverters { /** * Used when binding a parsed DateTime to a LocalDate field. - * @see DateTimeParser + * @see DateTimeParser **/ private static class DateTimeToLocalDateConverter implements Converter { public LocalDate convert(DateTime source) { @@ -67,9 +67,9 @@ final class JodaTimeConverters { } } - /** - * Used when binding a parsed DateTime to a LocalTime field. - * @see DateTimeParser + /** + * Used when binding a parsed DateTime to a LocalTime field. + * @see DateTimeParser */ private static class DateTimeToLocalTimeConverter implements Converter { public LocalTime convert(DateTime source) { @@ -77,9 +77,9 @@ final class JodaTimeConverters { } } - /** - * Used when binding a parsed DateTime to a LocalDateTime field. - * @see DateTimeParser + /** + * Used when binding a parsed DateTime to a LocalDateTime field. + * @see DateTimeParser */ private static class DateTimeToLocalDateTimeConverter implements Converter { public LocalDateTime convert(DateTime source) { @@ -87,9 +87,9 @@ final class JodaTimeConverters { } } - /** - * Used when binding a parsed DateTime to a DateMidnight field. - * @see DateTimeParser + /** + * Used when binding a parsed DateTime to a DateMidnight field. + * @see DateTimeParser */ private static class DateTimeToDateMidnightConverter implements Converter { public DateMidnight convert(DateTime source) { @@ -97,9 +97,9 @@ final class JodaTimeConverters { } } - /** - * Used when binding a parsed DateTime to an Instant field. - * @see DateTimeParser + /** + * Used when binding a parsed DateTime to an Instant field. + * @see DateTimeParser */ private static class DateTimeToInstantConverter implements Converter { public Instant convert(DateTime source) { @@ -107,19 +107,19 @@ final class JodaTimeConverters { } } - /** - * Used when binding a parsed DateTime to a MutableDateTime field. - * @see DateTimeParser + /** + * Used when binding a parsed DateTime to a MutableDateTime field. + * @see DateTimeParser */ private static class DateTimeToMutableDateTimeConverter implements Converter { public MutableDateTime convert(DateTime source) { return source.toMutableDateTime(); } } - - /** - * Used when binding a parsed DateTime to a java.util.Date field. - * @see DateTimeParser + + /** + * Used when binding a parsed DateTime to a java.util.Date field. + * @see DateTimeParser */ private static class DateTimeToDateConverter implements Converter { public Date convert(DateTime source) { @@ -127,9 +127,9 @@ final class JodaTimeConverters { } } - /** - * Used when binding a parsed DateTime to a java.util.Calendar field. - * @see DateTimeParser + /** + * Used when binding a parsed DateTime to a java.util.Calendar field. + * @see DateTimeParser */ private static class DateTimeToCalendarConverter implements Converter { public Calendar convert(DateTime source) { @@ -137,9 +137,9 @@ final class JodaTimeConverters { } } - /** - * Used when binding a parsed DateTime to a java.lang.Long field. - * @see DateTimeParser + /** + * Used when binding a parsed DateTime to a java.lang.Long field. + * @see DateTimeParser */ private static class DateTimeToLongConverter implements Converter { public Long convert(DateTime source) { @@ -162,7 +162,7 @@ final class JodaTimeConverters { * Used when printing a java.util.Calendar field with a ReadableInstantPrinter. * @see MillisecondInstantPrinter * @see JodaDateTimeFormatAnnotationFormatterFactory - */ + */ private static class CalendarToReadableInstantConverter implements Converter { public ReadableInstant convert(Calendar source) { return new DateTime(source); From ddddec87191e554d6e0f7b2d903af6f2ef9b03f8 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Sun, 30 Sep 2012 09:57:59 -0700 Subject: [PATCH 2/5] Corrected date pattern in JavaDocs The 'hh' pattern should be 'HH' as ISO dates use 24hr notation. --- .../springframework/format/annotation/DateTimeFormat.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spring-context/src/main/java/org/springframework/format/annotation/DateTimeFormat.java b/spring-context/src/main/java/org/springframework/format/annotation/DateTimeFormat.java index b09483274c..c5e526e8e0 100644 --- a/spring-context/src/main/java/org/springframework/format/annotation/DateTimeFormat.java +++ b/spring-context/src/main/java/org/springframework/format/annotation/DateTimeFormat.java @@ -82,13 +82,13 @@ public @interface DateTimeFormat { */ DATE, - /** - * The most common ISO Time Format hh:mm:ss.SSSZ e.g. 01:30:00.000-05:00. + /** + * The most common ISO Time Format HH:mm:ss.SSSZ e.g. 01:30:00.000-05:00. */ TIME, - /** - * The most common ISO DateTime Format yyyy-MM-dd'T'hh:mm:ss.SSSZ e.g. 2000-10-31 01:30:00.000-05:00. + /** + * The most common ISO DateTime Format yyyy-MM-dd'T'HH:mm:ss.SSSZ e.g. 2000-10-31 01:30:00.000-05:00. * The default if no annotation value is specified. */ DATE_TIME, From a26059f94a60257c2e0506ab70ef2a1364bd1d73 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Sun, 30 Sep 2012 10:00:20 -0700 Subject: [PATCH 3/5] Support DateTimeFormat annotation without Joda Dependency on Joda Time when using the @DateTimeFormat annotation is now optional. If Joda Time is not present the JDK SimpleDateFormat will be used to parse and print date patterns. If Joda time is present it will always be used in preference to SimpleDateFormat. Issue: SPR-6508 --- .../format/datetime/DateFormatter.java | 101 +++++- .../datetime/DateFormatterRegistrar.java | 123 +++++++ ...eTimeFormatAnnotationFormatterFactory.java | 85 +++++ ...eTimeFormatAnnotationFormatterFactory.java | 4 +- .../datetime/joda/JodaTimeConverters.java | 16 +- .../joda/JodaTimeFormatterRegistrar.java | 1 + .../DefaultFormattingConversionService.java | 47 +-- .../format/datetime/DateFormatterTests.java | 214 +++++++++++-- .../format/datetime/DateFormattingTests.java | 300 ++++++++++++++++++ 9 files changed, 806 insertions(+), 85 deletions(-) create mode 100644 spring-context/src/main/java/org/springframework/format/datetime/DateFormatterRegistrar.java create mode 100644 spring-context/src/main/java/org/springframework/format/datetime/DateTimeFormatAnnotationFormatterFactory.java create mode 100644 spring-context/src/test/java/org/springframework/format/datetime/DateFormattingTests.java diff --git a/spring-context/src/main/java/org/springframework/format/datetime/DateFormatter.java b/spring-context/src/main/java/org/springframework/format/datetime/DateFormatter.java index a371b4cf90..365800aba8 100644 --- a/spring-context/src/main/java/org/springframework/format/datetime/DateFormatter.java +++ b/spring-context/src/main/java/org/springframework/format/datetime/DateFormatter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * 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. @@ -19,11 +19,18 @@ package org.springframework.format.datetime; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; +import java.util.Collections; import java.util.Date; +import java.util.HashMap; import java.util.Locale; +import java.util.Map; import java.util.TimeZone; import org.springframework.format.Formatter; +import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.format.annotation.DateTimeFormat.ISO; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; /** * A formatter for {@link java.util.Date} types. @@ -31,15 +38,30 @@ import org.springframework.format.Formatter; * * @author Keith Donald * @author Juergen Hoeller + * @author Phillip Webb * @since 3.0 - * @see SimpleDateFormat + * @see SimpleDateFormat */ public class DateFormatter implements Formatter { + private static final Map ISO_PATTERNS; + static { + Map formats = new HashMap(); + formats.put(ISO.DATE, "yyyy-MM-dd"); + formats.put(ISO.TIME, "HH:mm:ss.SSSZ"); + formats.put(ISO.DATE_TIME, "yyyy-MM-dd'T'HH:mm:ss.SSSZ"); + ISO_PATTERNS = Collections.unmodifiableMap(formats); + } + + private String pattern; private int style = DateFormat.DEFAULT; + private String stylePattern; + + private ISO iso; + private TimeZone timeZone; private boolean lenient = false; @@ -80,6 +102,32 @@ public class DateFormatter implements Formatter { this.style = style; } + /** + * 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 + *