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>
精彩评论