Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
426 views
in Technique[技术] by (71.8m points)

java - how to validate input date against multiple patterns?

In my jsf application I know how to validate user input against one pattern in my ice:selectInputDate using a jsf converter:

   <f:convertDateTime pattern="MM/dd/yyyy"  />

but how should I do if I want to let the user be able to enter a date in format: "MM-dd-yyyy" too?

I think this can be done extending DateConverter from jsf but I already tried with that and I fail. Do you have a valid example to validate input date against multiple patterns?

Thanks.

UPDATE: I'm using jsf 1.2

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Create a custom converter which accepts multiple patterns by <f:attribute> on the component.

Here's how you'd like to have the view to look like:

<h:inputText id="input" value="#{bean.date}">
    <f:converter converterId="multiDateConverter" />
    <f:attribute name="pattern1" value="MM/dd/yyyy" />
    <f:attribute name="pattern2" value="MM-dd-yyyy" />
</h:inputText>

And here's how the converter can look like (for JSF 1.x, register it as

<converter-id>multiDateConverter</converter-id>

in faces-config.xml instead)

@FacesConverter(value="multiDateConverter")
public class MultiDateConverter implements Converter {

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) throws ConverterException {
        List<String> patterns = getPatterns(component);
        Date date = null;

        for (String pattern : patterns) {
            SimpleDateFormat sdf = new SimpleDateFormat(pattern);
            sdf.setLenient(false); // Don't parse dates like 33-33-3333.

            try {
                date = sdf.parse(value);
                break;
            } catch (ParseException ignore) {
                //
            }
        }

        if (date == null) {
            throw new ConverterException(new FacesMessage("Invalid date format, must match either of " + patterns));
        }

        return date;
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) throws ConverterException {
        return new SimpleDateFormat(getPatterns(component).get(0)).format((Date) value);
    }

    private static List<String> getPatterns(UIComponent component) {
        List<String> patterns = new ArrayList<String>();

        for (int i = 1; i < Integer.MAX_VALUE; i++) {
            String pattern = (String) component.getAttributes().get("pattern" + i);

            if (pattern != null) {
                patterns.add(pattern);
            } else {
                break;
            }
        }

        if (patterns.isEmpty()) {
            throw new IllegalArgumentException("Please provide <f:attribute name="patternX"> where X is the order number");
        }

        return patterns;
    }

}

Note that it only picks the first (default) pattern to redisplay the value. So in the above example, if you enter 05-10-2011, then it get redisplayed as 05/10/2011.


Unrelated to the concrete problem, the pattern MM-dd-yyyy isn't very common. Didn't you mean to use dd-MM-yyyy?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...