How to handle different date formats in Spring MVC

2020-07-17 06:53发布

问题:

Is it possible to handle different date format in a Spring MVC controller?

I know that setting something like this

@InitBinder
protected void initBinder(WebDataBinder binder) {
    SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
    binder.registerCustomEditor(Date.class, new CustomDateEditor(
            dateFormat, false));
}

I can handle dd/MM/yyyy format, but what if i want to parse also dates in yyyyMMddhhmmss format? Should I add multiple CustomDateEditors in my controller?

回答1:

If at a time you receive only one format of date, then you could simply create one instance of DateFormat based on format

for example

Decide the format based on the input

DateFormat df = null;
if(recievedDate.indexOf("//")!=-1){
    df = new SimpleDateFormat("dd/MM/yyyy")
}else{
    df = new SimpleDateFormat("yyyyMMddhhmmss")
}


回答2:

If you need it only at puntual cases, you can register the custom editor attached to a field in the form:

DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy", this.getLocale(context));
DateFormat dateTimeFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss SSS", this.getLocale(context));
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateTimeFormat, true));
binder.registerCustomEditor(Date.class, "name.of.input", new CustomDateEditor(dateTimeFormat, true));


回答3:

Inspired by Skipy

public class LenientDateParser extends PropertyEditorSupport {

private static final List<String> formats = new ArrayList<String>();

private String outputFormat;

static{
    formats.add("dd-MM-yyyy HH:ss");
    formats.add("dd/MM/yyyy HH:ss");
    formats.add("dd-MM-yyyy");
    formats.add("dd/MM/yyyy");
    formats.add("dd MMM yyyy");
    formats.add("MMM-yyyy HH:ss");
    formats.add("MMM-yyyy");
    formats.add("MMM yyyy");
}

public LenientDateParser(String outputFormat){
    this.outputFormat = outputFormat;
}

@Override
public void setAsText(String text) throws IllegalArgumentException {
    if(StringUtils.isEmpty(text))
        return;
    DateTime dt = null;
    for(String format : formats){

        try{

            dt = DateTime.parse(text, DateTimeFormat.forPattern(format));

            break;

        }catch(Exception e){
            if(log.isDebugEnabled())
                log.debug(e,e);
        }
    }
    if(dt != null)
        setValue(dt.toDate());
}

@Override
public String getAsText() {
    Date date = (Date) getValue();

    if(date == null)
        return "";

    DateTimeFormatter f = DateTimeFormat.forPattern(outputFormat);

    return f.print(date.getTime());

}
}


回答4:

How about this. the above can go out of whack pretty soon.

       public class MostLenientDateParser {
           private final List<String> supportedFormats;

           public MostLenientDateParser(List<String> supportedFormats) {
               this.supportedFormats = supportedFormats;
           }

           public Date parse(String dateValue) {
               for(String candidateFormat: supportedFormats) {
                   Date date = lenientParse(dateValue, candidateFormat);
                   if (date != null) {
                       return date;
                   }
               }
               throw new RuntimeException("tried so many formats, non matched");
           }

           private Date lenientParse(String dateCandidate, String dateFormat) {
               try {
                   return new SimpleDateFormat(dateFormat).parse(dateCandidate);
               } catch (Exception e) {
                   return null;
               }
           }
       }

This could also be referenced through Spring Converters via a CustomDateEditor implementation for form-data binding.



回答5:

For others having the same question, if you are using spring 3 You can use the awesome @DateTimeFormat(pattern="dd-MM-yyyy") in the field of your model.

Just make sure to register a conversionService with your org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter

You can have as much as you want of @DateTimeFormat in the same bean.



回答6:

Not a great idea to have lenient date formatters when dealing with multiple locales. A date like 10/11/2013 will get parsed correctly with both dd/MM/YYYY and MM/dd/YYYY