开发者

f:convertDateTime not being strict in pattern match?

开发者 https://www.devze.com 2023-04-08 03:28 出处:网络
I have a f:convertDateTime with a pattern of mm/dd/yyyy. However, people are able to enter 2/19/78 and it would be 0078 rather then 1978 or 2078. I want to force people to enter in all 4 digits.

I have a f:convertDateTime with a pattern of mm/dd/yyyy. However, people are able to enter 2/19/78 and it would be 0078 rather then 1978 or 2078. I want to force people to enter in all 4 digits.

I tried using a regexPattern validator, but that is complaining because it wants a string and not a Date object. Seems that the converters fire first and validators validate the converted value?

I guess I could write a custom converter or validator, but this seems like such a simple thing I figure I'm doing so开发者_运维百科mething wrong.

The javadocs for the convertor say it is strict in matching the pattern, but I'm not seeing that?

Any ideas or suggestions?

thanks!


It's only strict for days/months, not for years. Here's an extract of relevance from SimpleDateFormat javadoc which <f:convertDateTime> is using under the covers:

For parsing, if the number of pattern letters is more than 2, the year is interpreted literally, regardless of the number of digits. So using the pattern "MM/dd/yyyy", "01/11/12" parses to Jan 11, 12 A.D.

It's by design indeed not possible to fire validators before converters. Essentially, this one should have thrown a ConverterException because the input is not in the proper format. I'd create a custom converter which validates the pattern beforehand. Something like this:

@FacesConverter("validatingPatternDateTimeConverter")
public class ValidatingPatternDateTimeConverter extends DateTimeConverter {

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        String regex = getMandatoryAttribute(component, "validateRegex");
        String pattern = getMandatoryAttribute(component, "convertPattern");

        if (value != null && !value.matches(regex)) {
            throw new ConverterException(new FacesMessage(String.format("Invalid date, must be in pattern %s", pattern)));
        }

        setPattern(pattern);
        return super.getAsObject(context, component, value);
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        setPattern(getMandatoryAttribute(component, "convertPattern"));
        return super.getAsString(context, component, value);
    }

    private String getMandatoryAttribute(UIComponent component, String name) {
        String value = (String) component.getAttributes().get(name);

        if (value == null || value.isEmpty()) {
            throw new IllegalArgumentException(String.format("<f:attribute name=\"%s\"> is missing.", name));
        }

        return value;
    }

}

which is to be used as follows:

<h:inputText value="#{bean.date}">
    <f:converter converterId="validatingPatternDateTimeConverter" />
    <f:attribute name="validateRegex" value="\d{1,2}/\d{1,2}/\d{4}" />
    <f:attribute name="convertPattern" value="MM/dd/yyyy" />
</h:inputText>
0

精彩评论

暂无评论...
验证码 换一张
取 消