【问题标题】:Java RegEx Date Validation - Leap YearJava RegEx 日期验证 - 闰年
【发布时间】:2017-06-14 10:38:27
【问题描述】:

我正在做一项学校作业,但我只是坚持这个逻辑。基本上需要验证 1900 年到 2099 年之间年份的 RegEx(日期)。天数不能超过最大月份天数; (即 6 月有 30 天,因此 31 无效)以及考虑闰年,其中 2 月的日期可能是 29。这是我到目前为止所拥有的,但是当代码在 TestHarness 中运行时,我不断收到验证错误。我想我在这里有很多逻辑,但不知道如何解决。任何帮助都会很棒。

    public class RegexValidator {
            //class variables
            private String DATE_REGEX = "^((19|20)\\d\\d)-(0?[1-9]|
            1[012])-(0?[1-9]|[12][0-9]|3[01])$";

    public RegexValidator() {
            m_datePattern.compile(DATE_REGEX);
    }

    public boolean validDate(String date) {

        Matcher matcher = m_datePattern.matcher(date);

        int year = Integer.parseInt(matcher.group(1));//parse to calculate leap
        String month = matcher.group(2);
        String day = matcher.group(3);

        if(matcher.matches()) {
            matcher.reset();

            if(matcher.find()) {

                if(day.equals("31") && (month.equals("4") || month.equals("04") ||
                month.equals("6") || month.equals("06") || month.equals("9") ||
                month.equals("09") || month.equals("11"))) {
                    return false;
                } else if(month.equals("2") || month.equals("02")) {
                    //accounts for leap year
                    if(year % 4 == 0) {
                        if(day.equals("30") || day.equals("31")) {
                            return false;
                        } else {
                            return true;
                        }
                    } else {
                        if(day.equals("29") || day.equals("30") || day.equals("31")) {
                            return false;
                        } else {
                            return true;
                        }
                    }
                } else {
                    return true;
                }
            } else {
                return false;
            }
        } else {
            return false;
        }

    }

这是我遇到的错误列表:

    Error validating date '1900-1-11'

Error validating date '1900-1-11'

 ---- test date 1892-02-29 - expected false
 ---- Exception calling validDate: null
 ---- test date 1976-02-29 - expected true
 ---- Exception calling validDate: null
Error validating date '1976-02-29'

Error validating date '1976-02-29'

 ---- test date 2001-02-29 - expected false
 ---- Exception calling validDate: null
 ---- test date 2002-13-02 - expected false
 ---- Exception calling validDate: null
 ---- test date 2003-01-31 - expected true
 ---- Exception calling validDate: null
Error validating date '2003-01-31'

Error validating date '2003-01-31'

 ---- test date 1964-03-31 - expected true
 ---- Exception calling validDate: null
Error validating date '1964-03-31'

Error validating date '1964-03-31'

 ---- test date 1965-4-31 - expected false
 ---- Exception calling validDate: null
 ---- test date 1954-4-30 - expected true
 ---- Exception calling validDate: null
Error validating date '1954-4-30'

Error validating date '1954-4-30'

 ---- test date 1901-5-33 - expected false
 ---- Exception calling validDate: null
 ---- test date 1901-5-15 - expected true
 ---- Exception calling validDate: null
Error validating date '1901-5-15'

Error validating date '1901-5-15'

 ---- test date 2016-05-31 - expected true
 ---- Exception calling validDate: null
Error validating date '2016-05-31'

Error validating date '2016-05-31'

 ---- test date 2006-06-31 - expected false
 ---- Exception calling validDate: null
 ---- test date 20016-06-29 - expected false
 ---- Exception calling validDate: null
 ---- test date 1934-7-4 - expected true
 ---- Exception calling validDate: null
Error validating date '1934-7-4'

Error validating date '1934-7-4'

 ---- test date 2016-07-31 - expected true
 ---- Exception calling validDate: null
Error validating date '2016-07-31'

Error validating date '2016-07-31'

 ---- test date 2011-8-19 - expected true
 ---- Exception calling validDate: null
Error validating date '2011-8-19'

Error validating date '2011-8-19'

 ---- test date 2111-8-31 - expected false
 ---- Exception calling validDate: null
 ---- test date 2011-09-30 - expected true
 ---- Exception calling validDate: null
Error validating date '2011-09-30'

Error validating date '2011-09-30'

 ---- test date 2111-9-31 - expected false
 ---- Exception calling validDate: null
 ---- test date 2011-10-1 - expected true
 ---- Exception calling validDate: null
Error validating date '2011-10-1'

Error validating date '2011-10-1'

 ---- test date 2111-10-31 - expected false
 ---- Exception calling validDate: null
 ---- test date 2001-10-31 - expected true
 ---- Exception calling validDate: null
Error validating date '2001-10-31'

Error validating date '2001-10-31'

 ---- test date 2111-10-33 - expected false
 ---- Exception calling validDate: null
 ---- test date 2111-11-30 - expected false
 ---- Exception calling validDate: null
 ---- test date 2013-11-30 - expected true
 ---- Exception calling validDate: null
Error validating date '2013-11-30'

Error validating date '2013-11-30'

 ---- test date 2111-11-31 - expected false
 ---- Exception calling validDate: null
 ---- test date 2011-12-31 - expected true
 ---- Exception calling validDate: null
Error validating date '2011-12-31'

Error validating date '2011-12-31'

 ---- test date 2099-12-31 - expected true
 ---- Exception calling validDate: null
Error validating date '2099-12-31'

Error validating date '2099-12-31'

【问题讨论】:

  • 这些错误是秘密吗?
  • 他们不是.. 感谢您指出这一点。我已将它们添加到原始问题中。
  • 嗯,我马上发现的一个问题是 matcher.group(2) 返回第二组,即 19 或 20,不是月份。

标签: java regex validation


【解决方案1】:

如果m_datePatternPattern,则说明您使用的compile 不正确。 compile的签名是

public static Pattern compile(String regex)

因为是static,所以不适用于实例;它通常被称为

Pattern.compile(regex)

使用Pattern 对象而不是类名没有区别。因此,如果pPattern 对象,那么:

p.compile(regex)

Pattern.compile(regex) 做同样的事情,即使pnull。 对象被忽略。

最后,compile返回Pattern,这意味着必须将结果分配给Pattern对象:

pat = Pattern.compile(Regex);

您的代码没有在任何地方分配它。所以结果模式就被扔掉了。

最后,当您使用 group(n) 时,从 1 开始的组是正则表达式中以第一个 (、第二个 ( 等开头的捕获组。你的正则表达式是

"^((19|20)\\d\\d)-(0?[1-9]|1[012])-(0?[1-9]|[12][0-9]|3[01])$"

在这个正则表达式中,group(1) 是年份; group(2) 是 19 或 20; group(3) 是月份,group(4) 是日期。您的代码在月份和日期使用了错误的组。更改数字,或将 (19|20) 指定为 非捕获 组,如下所示:

"^((?:19|20)\\d\\d)-(0?[1-9]|1[012])-(0?[1-9]|[12][0-9]|3[01])$"

现在它不会被算作捕获组之一。

您的代码中可能还有其他错误。这些只是我注意到的。

【讨论】:

  • 谢谢大家的帮助。你的每一个答案实际上都帮助了我的一部分错误。分组错误是关键,而且我在 matcher.matches 或 matches.find 之前使用了 matcher.group。但是,在修复了这些错误之后,我仍然没有通过测试。正如@ajb 提到的,我的模式被忽略了,因为我实际上并没有分配它们。
【解决方案2】:

事实上,这段代码有很多问题。以下是我能够发现的:

  1. 您在matcher.matchesmatches.find 之前使用matcher.group。这是非法的并抛出IllegalStateException(请参阅JavaDoc 了解此方法here)。
  2. (19|20) 也是一个匹配组,因此第 2 组不会像您假设的那样对应于月份,而是对应于年份的前两位数。
  3. 您检查闰年的算法太简单了。考虑:

    @Test
    public void leapYearTricky() {
        Assert.assertFalse(new RegexValidator().validDate("1900-02-29"));
    }
    

另外,本身并不是一个错误,但matcher.matchesmatcher.resetmatcher.find 的意义何在?为什么matcher.matches() 不够用?

【讨论】:

    【解决方案3】:

    我有一个更好的解决方案(闰年):

    public static final String DATE_FORMAT_REG_EXP = "(^(((0[1-9]|1[0-9]|2[0-8])[\\/](0[1-9]|1[012]))|((29|30|31)[\\/](0[13578]|1[02]))|((29|30)[\\/](0[4,6,9]|11)))[\\/](19|[2-9][0-9])\\d\\d$)|(^29[\\/]02[\\/](19|[2-9][0-9])(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)$)";
    
    @Test
        public void testCheckValidateDate() {
            Assert.assertFalse("Wrong date, january do not have 32 days.", "32/01/2016".matches(DATE_FORMAT_REG_EXP));
            Assert.assertFalse("Wrong date, February do not have 30 days.", "30/02/2016".matches(DATE_FORMAT_REG_EXP));
            Assert.assertFalse("Wrong date, 2017 is not Leap year so 28 days", "29/02/2017".matches(DATE_FORMAT_REG_EXP));
            Assert.assertFalse("Wrong date, november have 30 days.", "31/11/2016".matches(DATE_FORMAT_REG_EXP));
            Assert.assertFalse("Wrong date, 16 instead of 2016.", "30/11/16".matches(DATE_FORMAT_REG_EXP));
    
            Assert.assertTrue("Good date.", "31/01/2016".matches(DATE_FORMAT_REG_EXP));
            Assert.assertTrue("Good date, 2016 is Leap year so 29 days", "29/02/2016".matches(DATE_FORMAT_REG_EXP));
            Assert.assertTrue("Good date.", "28/02/2016".matches(DATE_FORMAT_REG_EXP));
            Assert.assertTrue("Good date.", "28/02/2017".matches(DATE_FORMAT_REG_EXP));
            Assert.assertTrue("Good date.", "30/11/2016".matches(DATE_FORMAT_REG_EXP));
        }
    

    演示:

    Regexp - java - javascript - php - python - C# - ruby - rust - goland - perl

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-25
      • 2015-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-13
      相关资源
      最近更新 更多