2017-01-28 73 views
2

我正在上一個學校任務,我只是堅持這個邏輯。基本上需要驗證1900年至2099年間的RegEx(日期)。日期不能超過最大月份天數; (即六月有30天,所以31是無效的)以及佔2月日期可能是29歲的閏年。這是我迄今爲止,但是我從代碼在TestHarness中運行時不斷得到驗證錯誤。我想我在這裏有很多邏輯,但不知道如何解決。任何幫助都是極好的。Java RegEx日期驗證 - 閏年

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' 
+3

錯誤是祕密嗎? – jonrsharpe

+0

他們不是..謝謝指出。我已將它們添加到原始問題中。 – devjitsu

+0

那麼,我馬上發現的一個問題是,'matcher.group(2)'返回第二個組,它將在本月不是19或20。 – ajb

回答

1

如果m_datePatternPattern,你使用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])$" 

現在將不會被計算作爲捕獲基團之一。

代碼中可能存在其他錯誤。這些只是我注意到的。

+0

謝謝大家的幫助。你的每一個答案實際上幫助了我錯誤的一部分。分組錯誤是關鍵,也是我在matcher.matches或matches.find之前使用matcher.group。但是,在修復這些錯誤之後,我仍然沒有通過測試。正如@ajb所提到的那樣,我的模式被忽略了,因爲我實際上沒有指定它們。 – devjitsu

1

這段代碼實際上有很多錯誤。以下是我已經能夠發現的那些:

  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()夠了?

1

我有一個更好的解決方案(閏年):

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