使用表达式语言验证日期的JSF

3
我需要检查我的出生日期输入字段的值。有几种可能性:dd.MM.yyyydd.M.yyyyd.MM.yyyyd.m.yyyy,以及dd.MM.yydd.M.yyd.MM.yyd.m.yy。例如,您可以输入07.03.1993,7.3.93或其他内容。
以下正则表达式示例仅检查格式验证,但不检查日期是否存在(例如,将允许29.02.2011或47.02.2011)。
String s = (String) arg2;
        String pattern = "^(\\d{2}|\\d{1})\\.(\\d{2}|\\d{1})\\.(\\d{2}|\\d{4})$";
        Pattern p = Pattern.compile(pattern);
        Matcher m = p.matcher(s);

        if (m.matches()) {
            System.out.println(("date correct"));
        } else {
            System.out.println("date incorrect");
        }

编辑:我刚刚创建了以下正则表达式语句,现在它检查月份是否大于12且日期是否大于31。我认为应该先使用正则表达式,然后使用SimpleDateFormat验证日期。
String s = "^((0?[1-9]|[12][0-9]|3[01])\\.(0?[1-9]|1[012])\\.((19|20)\\d{2})$";
2个回答

2
如果不一定需要使用正则表达式,你可以尝试使用java.text.SimpleDateFormatparse方法将字符串转换为日期,并查看是否成功。
如果成功(你得到了一个有效的Date对象),那么你在表单(或输入)中输入的就是有效的日期。如果不成功,parse函数会返回null,表示你输入的字符串无效。
这里是parse方法的Java文档(链接)
编辑:如果你不想使用setLenient进行额外的验证,你可以使用从parse获取的Date并使用相同的格式将其转换回String。然后只需比较转换后得到的String和你提供的输入字符串是否匹配。如果匹配,则说明你有有效的输入。

2
SimpleDateFormat.parse 不进行验证。例如,如果您执行 Date d = new SimpleDateFormat("yyyy-MM-dd").parse("2012-01-32");,那么日期 d 将指向 2 月 1 日,因为天数“溢出”到了该月。 - Alderath
3
不是这样的,Alderath,使用 setLenient(false),然后你的日期将会抛出异常。 - yves.beutler
你可以通过确定闰年并检查 29/02 来添加更多的验证。但是,如果解析方法允许在非闰年中使用 29/02,那么 Date 包含什么?我认为返回的 Date 对象不会允许在非闰年中使用 29/02。你可以尝试使用静态方法 java.sql.Date.valueOf 并使用 java.sql.Date 而不是 java.util.Date - lucian.pantelimon
谢谢@lucian.pantelimon,我将结合您的SimpleDateFormat和我的正则表达式。如果它有效,我会向您展示。 - yves.beutler
@YvesBeutler 不错。我错过了那个。当我注意到没有抛出任何异常时,我感到很惊讶。在我看来,setLenient(false) 应该是默认值,而不是相反。当调用 parse 时,你期望有错误报告。 - Alderath
显示剩余2条评论

0
你可以将其拆分以获取日期的日和月份部分。
然后你可以做类似这样的事情:
final int dayToCheck = 32; // user input
final int month = 2; // user input
final int year = 1981; // user input        

final Calendar cal = Calendar.getInstance();
cal.set(year, month, 1); // day doesn't need to be the user input, it can be any day in the month you want to check

if (cal.getActualMaximum(Calendar.DAY_OF_MONTH) > dayToCheck) {

    // the day is invalid
}
if (cal.getActualMinimum(Calendar.DAY_OF_MONTH) < dayToCheck) {

    // again, the day is invalid
}

你可以使用Calendar.MONTH字段进行相同的检查。

我还没有检查它是否编译通过,但你应该能够理解。


如果您写入 cal.set(2011,02,29),不会出现错误。因此,我更喜欢 @lucian.pantelimon 的解决方案,并将其与我的工作结合起来。 - yves.beutler
正如我在答案中所述:创建日历时,您不应设置完整的用户输入。您只需要设置年份和月份(日期始终可以设置为1)。然后使用cal.getActualMaximum(Calendar.DAY_OF_MONTH)将其与用户输入的日期进行比较。 - Simeon
是的,没错。但我认为让 SimpleDateFormat 检查日期是否正确比像你这样的自制方案更好。 - yves.beutler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接