Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support YearMonth and MonthDay with the @DateTimeFormat annotation #1215

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@
import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime;
import org.joda.time.LocalTime;
import org.joda.time.MonthDay;
import org.joda.time.ReadableInstant;
import org.joda.time.ReadablePartial;
import org.joda.time.YearMonth;
import org.joda.time.format.DateTimeFormatter;

import org.springframework.context.support.EmbeddedValueResolutionSupport;
Expand All @@ -42,6 +44,7 @@
*
* @author Keith Donald
* @author Juergen Hoeller
* @author Kazuki Shimizu
* @since 3.0
* @see DateTimeFormat
*/
Expand All @@ -65,6 +68,8 @@ public class JodaDateTimeFormatAnnotationFormatterFactory extends EmbeddedValueR
fieldTypes.add(Date.class);
fieldTypes.add(Calendar.class);
fieldTypes.add(Long.class);
fieldTypes.add(YearMonth.class);
fieldTypes.add(MonthDay.class);
FIELD_TYPES = Collections.unmodifiableSet(fieldTypes);
}

Expand Down Expand Up @@ -101,6 +106,12 @@ else if (LocalTime.class == fieldType) {
else if (LocalDateTime.class == fieldType) {
return new LocalDateTimeParser(getFormatter(annotation, fieldType));
}
else if (YearMonth.class == fieldType) {
return new YearMonthParser(getFormatter(annotation, fieldType));
}
else if (MonthDay.class == fieldType) {
return new MonthDayParser(getFormatter(annotation, fieldType));
}
else {
return new DateTimeParser(getFormatter(annotation, fieldType));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2002-2016 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 org.joda.time.MonthDay;
import org.joda.time.format.DateTimeFormatter;
import org.springframework.format.Parser;

import java.text.ParseException;
import java.util.Locale;

/**
* Parses Joda {@link MonthDay} instances using a
* {@link DateTimeFormatter}.
*
* @author Kazuki Shimizu
* @since 4.3.4
*/
public final class MonthDayParser implements Parser<MonthDay> {

private final DateTimeFormatter formatter;

/**
* Create a new DateTimeParser.
* @param formatter the Joda DateTimeFormatter instance
*/
public MonthDayParser(DateTimeFormatter formatter) {
this.formatter = formatter;
}

@Override
public MonthDay parse(String text, Locale locale) throws ParseException {
return MonthDay.parse(text, JodaTimeContextHolder.getFormatter(this.formatter, locale));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2002-2016 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 org.joda.time.YearMonth;
import org.joda.time.format.DateTimeFormatter;
import org.springframework.format.Parser;

import java.text.ParseException;
import java.util.Locale;

/**
* Parses Joda {@link YearMonth} instances using a
* {@link DateTimeFormatter}.
*
* @author Kazuki Shimizu
* @since 4.3.4
*/
public final class YearMonthParser implements Parser<YearMonth> {

private final DateTimeFormatter formatter;

/**
* Create a new DateTimeParser.
* @param formatter the Joda DateTimeFormatter instance
*/
public YearMonthParser(DateTimeFormatter formatter) {
this.formatter = formatter;
}

@Override
public YearMonth parse(String text, Locale locale) throws ParseException {
return YearMonth.parse(text, JodaTimeContextHolder.getFormatter(this.formatter, locale));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.time.MonthDay;
import java.time.YearMonth;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
Expand All @@ -39,6 +41,7 @@
* JSR-310 <code>java.time</code> package in JDK 8.
*
* @author Juergen Hoeller
* @author Kazuki Shimizu
* @since 4.0
* @see org.springframework.format.annotation.DateTimeFormat
*/
Expand All @@ -56,6 +59,8 @@ public class Jsr310DateTimeFormatAnnotationFormatterFactory extends EmbeddedValu
fieldTypes.add(ZonedDateTime.class);
fieldTypes.add(OffsetDateTime.class);
fieldTypes.add(OffsetTime.class);
fieldTypes.add(YearMonth.class);
fieldTypes.add(MonthDay.class);
FIELD_TYPES = Collections.unmodifiableSet(fieldTypes);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.MonthDay;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.time.YearMonth;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
Expand All @@ -34,6 +36,7 @@
* using a {@link java.time.format.DateTimeFormatter}) (the contextual one, if available).
*
* @author Juergen Hoeller
* @author Kazuki Shimizu
* @since 4.0
* @see DateTimeContextHolder#getFormatter
* @see java.time.LocalDate#parse(CharSequence, java.time.format.DateTimeFormatter)
Expand All @@ -42,6 +45,8 @@
* @see java.time.ZonedDateTime#parse(CharSequence, java.time.format.DateTimeFormatter)
* @see java.time.OffsetDateTime#parse(CharSequence, java.time.format.DateTimeFormatter)
* @see java.time.OffsetTime#parse(CharSequence, java.time.format.DateTimeFormatter)
* @see java.time.YearMonth#parse(CharSequence, java.time.format.DateTimeFormatter)
* @see java.time.MonthDay#parse(CharSequence, java.time.format.DateTimeFormatter)
*/
public final class TemporalAccessorParser implements Parser<TemporalAccessor> {

Expand Down Expand Up @@ -83,6 +88,12 @@ else if (OffsetDateTime.class == this.temporalAccessorType) {
else if (OffsetTime.class == this.temporalAccessorType) {
return OffsetTime.parse(text, formatterToUse);
}
else if (YearMonth.class == this.temporalAccessorType) {
return YearMonth.parse(text, formatterToUse);
}
else if (MonthDay.class == this.temporalAccessorType) {
return MonthDay.parse(text, formatterToUse);
}
else {
throw new IllegalStateException("Unsupported TemporalAccessor type: " + this.temporalAccessorType);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
* @author Keith Donald
* @author Juergen Hoeller
* @author Phillip Webb
* @author Kazuki Shimizu
*/
public class JodaTimeFormattingTests {

Expand Down Expand Up @@ -495,6 +496,16 @@ public void testBindYearMonth() {
assertTrue(binder.getBindingResult().getFieldValue("yearMonth").toString().equals("2007-12"));
}

@Test
public void testBindYearMonthAnnotatedPattern() {
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("yearMonthAnnotatedPattern", "12/2007");
binder.bind(propertyValues);
assertEquals(0, binder.getBindingResult().getErrorCount());
assertTrue(binder.getBindingResult().getFieldValue("yearMonthAnnotatedPattern").toString().equals("12/2007"));
assertEquals(YearMonth.parse("2007-12"), binder.getBindingResult().getRawFieldValue("yearMonthAnnotatedPattern"));
}

@Test
public void testBindMonthDay() {
MutablePropertyValues propertyValues = new MutablePropertyValues();
Expand All @@ -504,6 +515,15 @@ public void testBindMonthDay() {
assertTrue(binder.getBindingResult().getFieldValue("monthDay").toString().equals("--12-03"));
}

@Test
public void testBindMonthDayAnnotatedPattern() {
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("monthDayAnnotatedPattern", "1/3");
binder.bind(propertyValues);
assertEquals(0, binder.getBindingResult().getErrorCount());
assertTrue(binder.getBindingResult().getFieldValue("monthDayAnnotatedPattern").toString().equals("1/3"));
assertEquals(MonthDay.parse("--01-03"), binder.getBindingResult().getRawFieldValue("monthDayAnnotatedPattern"));
}

@SuppressWarnings("unused")
private static class JodaTimeBean {
Expand Down Expand Up @@ -568,8 +588,14 @@ private static class JodaTimeBean {

private YearMonth yearMonth;

@DateTimeFormat(pattern = "MM/yyyy")
private YearMonth yearMonthAnnotatedPattern;

private MonthDay monthDay;

@DateTimeFormat(pattern = "M/d")
private MonthDay monthDayAnnotatedPattern;

private final List<JodaTimeBean> children = new ArrayList<>();

public LocalDate getLocalDate() {
Expand Down Expand Up @@ -757,6 +783,14 @@ public void setYearMonth(YearMonth yearMonth) {
this.yearMonth = yearMonth;
}

public YearMonth getYearMonthAnnotatedPattern() {
return yearMonthAnnotatedPattern;
}

public void setYearMonthAnnotatedPattern(YearMonth yearMonthAnnotatedPattern) {
this.yearMonthAnnotatedPattern = yearMonthAnnotatedPattern;
}

public MonthDay getMonthDay() {
return monthDay;
}
Expand All @@ -765,6 +799,14 @@ public void setMonthDay(MonthDay monthDay) {
this.monthDay = monthDay;
}

public MonthDay getMonthDayAnnotatedPattern() {
return monthDayAnnotatedPattern;
}

public void setMonthDayAnnotatedPattern(MonthDay monthDayAnnotatedPattern) {
this.monthDayAnnotatedPattern = monthDayAnnotatedPattern;
}

public List<JodaTimeBean> getChildren() {
return children;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
* @author Keith Donald
* @author Juergen Hoeller
* @author Phillip Webb
* @author Kazuki Shimizu
*/
public class DateTimeFormattingTests {

Expand Down Expand Up @@ -372,6 +373,16 @@ public void testBindYearMonth() {
assertTrue(binder.getBindingResult().getFieldValue("yearMonth").toString().equals("2007-12"));
}

@Test
public void testBindYearMonthAnnotatedPattern() {
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("yearMonthAnnotatedPattern", "12/2007");
binder.bind(propertyValues);
assertEquals(0, binder.getBindingResult().getErrorCount());
assertTrue(binder.getBindingResult().getFieldValue("yearMonthAnnotatedPattern").toString().equals("12/2007"));
assertEquals(YearMonth.parse("2007-12"), binder.getBindingResult().getRawFieldValue("yearMonthAnnotatedPattern"));
}

@Test
public void testBindMonthDay() {
MutablePropertyValues propertyValues = new MutablePropertyValues();
Expand All @@ -381,6 +392,16 @@ public void testBindMonthDay() {
assertTrue(binder.getBindingResult().getFieldValue("monthDay").toString().equals("--12-03"));
}

@Test
public void testBindMonthDayAnnotatedPattern() {
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("monthDayAnnotatedPattern", "1/3");
binder.bind(propertyValues);
assertEquals(0, binder.getBindingResult().getErrorCount());
assertTrue(binder.getBindingResult().getFieldValue("monthDayAnnotatedPattern").toString().equals("1/3"));
assertEquals(MonthDay.parse("--01-03"), binder.getBindingResult().getRawFieldValue("monthDayAnnotatedPattern"));
}


public static class DateTimeBean {

Expand Down Expand Up @@ -419,6 +440,12 @@ public static class DateTimeBean {

private YearMonth yearMonth;

@DateTimeFormat(pattern="MM/uuuu")
private YearMonth yearMonthAnnotatedPattern;

@DateTimeFormat(pattern="M/d")
private MonthDay monthDayAnnotatedPattern;

private MonthDay monthDay;

private final List<DateTimeBean> children = new ArrayList<>();
Expand Down Expand Up @@ -535,6 +562,14 @@ public void setYearMonth(YearMonth yearMonth) {
this.yearMonth = yearMonth;
}

public YearMonth getYearMonthAnnotatedPattern() {
return yearMonthAnnotatedPattern;
}

public void setYearMonthAnnotatedPattern(YearMonth yearMonthAnnotatedPattern) {
this.yearMonthAnnotatedPattern = yearMonthAnnotatedPattern;
}

public MonthDay getMonthDay() {
return monthDay;
}
Expand All @@ -543,6 +578,14 @@ public void setMonthDay(MonthDay monthDay) {
this.monthDay = monthDay;
}

public MonthDay getMonthDayAnnotatedPattern() {
return monthDayAnnotatedPattern;
}

public void setMonthDayAnnotatedPattern(MonthDay monthDayAnnotatedPattern) {
this.monthDayAnnotatedPattern = monthDayAnnotatedPattern;
}

public List<DateTimeBean> getChildren() {
return children;
}
Expand Down