The other day I found myself needing my SpringMVC controller to be able to map multiple formats to a date. I was using the CustomDateEditor
to map the normal MM/dd/yyyy
format, but then I found that I also needed to be able to accept the EEE MMM dd HH:mm:ss zzz yyyy
format.
Not being able to find an existing solution, I decided to roll my own. Enjoy.
Below shows how it is used in the controller, the actual editor class, and then the test
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@InitBinder | |
public void initBinder(WebDataBinder binder) { | |
DateFormat printFormat = new SimpleDateFormat("MM/dd/yyyy", Locale.getDefault()); | |
printFormat.setLenient(false); | |
DateFormat sortFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.getDefault()); | |
sortFormat.setLenient(false); | |
binder.registerCustomEditor(Date.class, new ExpandableCustomDateEditor(printFormat, Arrays.asList(printFormat, sortFormat), true)); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* | |
*/ | |
package com.bmchild.spring; | |
import java.beans.PropertyEditorSupport; | |
import java.text.DateFormat; | |
import java.text.ParseException; | |
import java.util.ArrayList; | |
import java.util.Date; | |
import java.util.List; | |
import org.apache.commons.lang.StringUtils; | |
/** | |
* An extension of the CustomDateEditor that allows more than 1 format for parsing dates. | |
* | |
* @author bchild | |
* | |
*/ | |
public class ExpandableCustomDateEditor extends PropertyEditorSupport { | |
private DateFormat printFormatter; | |
private List<DateFormat> parseFormatters; | |
private boolean allowEmpty; | |
/** | |
* @param printFormatter formatter for printing to forms | |
* @param parseFormatters formatters to try to parse a date string | |
* @param allowEmpty if true, empty values will be parse as null | |
*/ | |
public ExpandableCustomDateEditor(DateFormat printFormatter, List<DateFormat> parseFormatters, boolean allowEmpty) { | |
this.printFormatter = printFormatter; | |
this.parseFormatters = parseFormatters; | |
this.allowEmpty = allowEmpty; | |
} | |
/* (non-Javadoc) | |
* @see java.beans.PropertyEditorSupport#setAsText(java.lang.String) | |
*/ | |
@Override | |
public void setAsText(String text) throws IllegalArgumentException { | |
if (this.allowEmpty && StringUtils.isEmpty(text)) { | |
// Treat empty String as null value. | |
setValue(null); | |
} else if (text != null) { | |
boolean parseable = false; | |
List<String> errors = new ArrayList<String>(); | |
for(DateFormat formatter : this.parseFormatters) { | |
try { | |
Date date = formatter.parse(text); | |
setValue(date); | |
parseable = true; | |
break; | |
} catch (ParseException e) { | |
errors.add(e.getMessage()); | |
} | |
} | |
if(!parseable) { | |
throw new IllegalArgumentException("Unparseable string: " + errors.toString()); | |
} | |
} | |
} | |
/** | |
* Format the Date as String, using the specified DateFormat. | |
*/ | |
@Override | |
public String getAsText() { | |
Date value = (Date) getValue(); | |
return (value != null ? this.printFormatter.format(value) : ""); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* | |
*/ | |
package com.bmchild.spring; | |
import static org.junit.Assert.assertEquals; | |
import static org.junit.Assert.assertNull; | |
import java.text.DateFormat; | |
import java.text.SimpleDateFormat; | |
import java.util.Arrays; | |
import java.util.Date; | |
import java.util.Locale; | |
import org.junit.Test; | |
/** | |
* @author bchild | |
* | |
*/ | |
public class ExpandableCustomDateEditorTest { | |
/** | |
* Test method for {@link com.bmchild.spring.ExpandableCustomDateEditor#setAsText(java.lang.String)}. | |
*/ | |
@Test | |
public void testSetAsTextString() { | |
DateFormat printFormatter = new SimpleDateFormat("MM/dd/yyyy"); | |
DateFormat anotherFormatter = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.getDefault()); | |
ExpandableCustomDateEditor editor = | |
new ExpandableCustomDateEditor(printFormatter, Arrays.asList(printFormatter, anotherFormatter), true); | |
Date now = new Date(); | |
String formatted = printFormatter.format(now); | |
editor.setAsText(formatted); | |
assertEquals(formatted, printFormatter.format((Date)editor.getValue())); | |
formatted = anotherFormatter.format(now); | |
editor.setAsText(formatted); | |
assertEquals(formatted, anotherFormatter.format((Date)editor.getValue())); | |
} | |
@Test | |
public void testSetTextAsStringEmpty() { | |
DateFormat printFormatter = new SimpleDateFormat("MM/dd/yyyy"); | |
ExpandableCustomDateEditor editor = | |
new ExpandableCustomDateEditor(printFormatter, Arrays.asList(printFormatter), true); | |
editor.setAsText(""); | |
assertNull(editor.getValue()); | |
editor.setAsText(null); | |
assertNull(editor.getValue()); | |
} | |
@Test(expected = IllegalArgumentException.class) | |
public void testSetTextAsStringUnparseable() { | |
DateFormat printFormatter = new SimpleDateFormat("MM/dd/yyyy"); | |
ExpandableCustomDateEditor editor = | |
new ExpandableCustomDateEditor(printFormatter, Arrays.asList(printFormatter), true); | |
editor.setAsText("gfgfgdfs"); | |
} | |
/** | |
* Test method for {@link com.bmchild.spring.ExpandableCustomDateEditor#getAsText()}. | |
*/ | |
@Test | |
public void testGetAsText() { | |
DateFormat printFormatter = new SimpleDateFormat("MM/dd/yyyy"); | |
DateFormat anotherFormatter = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.getDefault()); | |
ExpandableCustomDateEditor editor = | |
new ExpandableCustomDateEditor(printFormatter, Arrays.asList(printFormatter, anotherFormatter), true); | |
Date now = new Date(); | |
String formatted = printFormatter.format(now); | |
editor.setValue(now); | |
assertEquals(formatted, editor.getAsText()); | |
} | |
} |
No comments:
Post a Comment