Register multiple date format for binding properities

Grails可以自动把params里面的参数绑定到domain class。有些时候为了能够绑定自定义的日期格式,例如"yyyy-MM-dd",需要register一个自己的CustomDateEditor。

有时候还有需求要绑定多种格式的日期,例如"yyyy/MM/dd"、"yyyy-MM-dd HH:mm:ss"等等,这时候就需要一个支持多种日期格式的CustomDateEditor,解决方法如下:

1. 新建一个MultipleDateEditor.groovy
package com.myapp

import java.beans.PropertyEditorSupport;
import java.text.ParseException;
import java.util.Date;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.commons.lang.time.DateUtils;
import org.springframework.util.StringUtils;

/**
 * Property editor for java.util.Date, supporting multiple custom input formats
 * and custom output formats.  This class utilizes DateUtils and
 * DateFormatUtils of Apache Commons Lang, and has been tested for version 2.4
 * but may work with older versions.
 *
 * It should be noted that the date input formats should be inserted into the
 * array based on the length of the string, longest to shortest.
 *
 * This is not meant to be used as system PropertyEditor but rather as
 * locale-specific date editor within custom controller code, parsing
 * user-entered number strings into Date properties of beans and rendering
 * them in the UI form.
 *
 * In web MVC code, this editor will typically be registered with
 * binder.registerCustomEditor calls in a custom initBinder method.
 *
 * @author jpreston
 * @see java.beans.PropertyEditorSupport
 * @see java.util.Date
 * @see org.apache.commons.lang.time.DateUtils
 * @see org.apache.commons.lang.time.DateFormatUtils
 */
public class MultipleDateEditor extends PropertyEditorSupport {

    /**
     * The date format used to format a Date into a String
     */
    public final static String DEFAULT_OUTPUT_FORMAT = "dd/mm/yyyy";
    /**
     * The date formats used to parse a String into a Date
     */
    public final static String[] DEFAULT_INPUT_FORMATS = [
        "dd/mm/yyyy hh:mm:ss",
        "dd-mm-yyyy hh:mm:ss",
        "dd/mm/yy hh:mm:ss",
        "dd-mm-yy hh:mm:ss",
        "dd/mm/yyyy",
        "dd-mm-yyyy",
        "dd/mm/yy",
        "dd-mm-yy"
    ];
    /** The format used to convert a Date into a String */
    private String outputFormat;
    /** An array of date formats used to convert a String into a Date */
    private String[] inputFormats;
    /** Allow empty strings to be parsed instead of treated as null */
    private boolean allowEmpty;

    /**
     * Create a new MultipleDateEditor instance using the default values
     */
    public MultipleDateEditor() {
        outputFormat = MultipleDateEditor.DEFAULT_OUTPUT_FORMAT;
        inputFormats = MultipleDateEditor.DEFAULT_INPUT_FORMATS;
        allowEmpty = false;
    }

    /**
     * Create a new MultipleDateEditor instance using the given date
     * input and output formats.
     *
     * The "allowEmpty" parameter states if an empty String should be allowed for
     * parsing, i.e. get interpreted as null value. Otherwise, an
     * IllegalArgumentException gets thrown in that case.
     *
     * @param outputFormat The format used to convert a Date into a String
     * @param inputFormats An array of date formats used to convert a String into a Date
     */
    public MultipleDateEditor(String outputFormat, String[] inputFormats) {
        this.outputFormat = outputFormat;
        this.inputFormats = inputFormats;
        allowEmpty = false;
    }

    /**
     * Create a new MultipleDateEditor instance using the given date
     * input and output formats.
     *
     * The "allowEmpty" parameter states if an empty String should be allowed for
     * parsing, i.e. get interpreted as null value. Otherwise, an
     * IllegalArgumentException gets thrown in that case.
     *
     * @param outputFormat The format used to convert a Date into a String
     * @param inputFormats An array of date formats used to convert a String into a Date
     * @param allowEmpty Allow empty strings to be parsed instead of treated as null
     */
    public MultipleDateEditor(String outputFormat, String[] inputFormats,
            boolean allowEmpty) {
        this.outputFormat = outputFormat;
        this.inputFormats = inputFormats;
        this.allowEmpty = allowEmpty;
    }

    /**
     * Format the Date as String, using the specified outputFormat.
     *
     * If allowEmpty is true (default is false), and the Date is null, an empty
     * String will be returned; otherwise it is possible that a NPE or other
     * parsing exception will occur.
     *
     * @return The string value of the Date
     */
    @Override
    public String getAsText() {
        if (allowEmpty && getValue() == null) {
            return "";
        }

        return DateFormatUtils.format((Date) getValue(), outputFormat);
    }

    /**
     * Parse the Date from the given text, using the first matching date format
     * specified in the inputFormats array.
     *
     * If no matching input format is found, an IllegalArgumentException is thrown.
     *
     * If allowEmpty is true (default is false), and the String is null, the Date
     * will be interpreted as null; otherwise an IllegalArgumentException is thrown.
     *
     * @param text the text to convert into a java.util.Date
     * @throws IllegalArgumentException thrown if no matching format is found
     */
    @Override
    public void setAsText(String text) throws IllegalArgumentException {
        try {
            if (StringUtils.hasText(text)) {
                setValue(DateUtils.parseDate(text, inputFormats));
            } else {
                if (allowEmpty) {
                    setValue(null);
                } else {
                    throw new IllegalArgumentException(
                            "The text specified for parsing is null");
                }
            }
        } catch (ParseException ex) {
            throw new IllegalArgumentException("Could not parse text ["
                    + text + "] into any available date input formats", ex);
        }
    }

    /**
     * If allowEmpty is true (default is false), and the Date is null, an empty
     * String will be returned; otherwise it is possible that a NPE or other
     * parsing exception will occur.
     *
     * If allowEmpty is true (default is false), and the String is null, the Date
     * will be interpreted as null; otherwise an IllegalArgumentException is thrown.
     *
     * @return whether empty strings are allowed
     */
    public boolean isAllowEmpty() {
        return allowEmpty;
    }

    /**
     * If allowEmpty is true (default is false), and the Date is null, an empty
     * String will be returned; otherwise it is possible that a NPE or other
     * parsing exception will occur.
     *
     * If allowEmpty is true (default is false), and the String is null, the Date
     * will be interpreted as null; otherwise an IllegalArgumentException is thrown.
     *
     * @param allowEmpty whether empty strings should be allowed
     */
    public void setAllowEmpty(boolean allowEmpty) {
        this.allowEmpty = allowEmpty;
    }

    /**
     * Get the date formats used to parse a String into a Date
     *
     * @return The date formats used to parse a String into a Date
     */
    public String[] getInputFormats() {
        return inputFormats;
    }

    /**
     * Set the date formats used to parse a String into a Date.  It should be
     * noted that the date formats should be inserted into the array based
     * on the length of the format, longest to shortest.
     *
     *
     * @param inputFormats The date formats used to parse a String into a Date
     */
    public void setInputFormats(String[] inputFormats) {
        this.inputFormats = inputFormats;
    }

    /**
     * Get the format used to convert a Date into a String
     *
     * @return The format used to convert a Date into a String
     */
    public String getOutputFormat() {
        return outputFormat;
    }

    /**
     * Set the format used to convert a Date into a String
     *
     * @param outputFormat The format used to convert a Date into a String
     */
    public void setOutputFormat(String outputFormat) {
        this.outputFormat = outputFormat;
    }
}


2. 新建MultipleDateEditorRegistrar.groovy
package com.myapp

import org.springframework.beans.PropertyEditorRegistrar
import org.springframework.beans.PropertyEditorRegistry

/**
 * binding date properties with customer format
 * "yyyy-MM-dd HH:mm:ss"
 * "yyyy-MM-dd HH:mm"
 * "yyyy-MM-dd"
 */
public class MultipleDateEditorRegistrar implements PropertyEditorRegistrar {
  public void registerCustomEditors(PropertyEditorRegistry registry) {
      registry.registerCustomEditor(Date.class, 
new MultipleDateEditor("yyyy-MM-dd HH:mm:ss",
              ["yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM-dd"] as String[], true));
  }
}


3. 注册到spring beans
beans = {
        customPropertyEditorRegistrar(com.nazuche.MultipleDateEditorRegistrar)
}



Reference: http://forum.springsource.org/showthread.php?78118-Multiple-Date-Formats-in-a-Form

你可能感兴趣的:(spring,grails,Date format)