2011-05-13 403 views
1
/** 
* Validates a date in String data type according to the given date format. 
* 
* @param validDateFormat 
*   valid date format e.g. YYYY/MM/DD 
* @param strDate 
*   - the date to be validated 
* @return true if the date is valid according to the given format 
*/ 
public static boolean isValidDate(final String strDate, final String validDateFormat) { 
    boolean result = true; 

    try { 
     if (StringUtils.isNotBlank(validDateFormat) && StringUtils.isNotBlank(strDate) 
       && StringUtils.isNotEmpty(strDate)) { 
      dateValidator = new SimpleDateFormat(validDateFormat, Locale.ENGLISH); 
      dateValidator.setLenient(false); 
      dateValidator.parse(strDate); 


      Log.i(TAG, "***Date entered: "+ strDate + 
        "\nDate parsed back: "+dateValidator.format(dateValidator.parse(strDate))); 

      dateValidator = null; 
     } 
     else 
     { 
      result = false; 
     } 
    } catch (final ParseException e) { 
     result = false; 
    } catch (final IllegalArgumentException e) { 
     result = false; 
    } catch (final Exception e) { 
     result = false; 
    } 

    return result; 
} 

當我在輸入例:SimpleDateFormat的錯誤

boolean result = isValidDate("21/May/201l", "dd/MMM/yyyy"); 
//result = true 

提醒的是,輸入的不是兩千年十一點,其兩百一個+一個字母「l」。

日誌:

***Date entered: 21/May/201l 
    Date parsed back: 21/May/0201 

它不拋出任何異常,並不會使它假!!!!

WHYYYYYYYYYY !?

回答

2

更新:一個想法是強加給你輸入一個相當嚴格的限制:輸入日期字符串和格式字符串必須匹配,正好是;你可以通過做一些像執行本:

Date parsed = dateValidator.parse(strDate); 
return strDate.equals(dateValidator.format(parsed)); 

換句話說,驗證,格式化實際Date對象返回一個字符串,它是相同的東西也通過這將確保你不會有錯誤的陽性。當格式字符串中存在實際上無效的字符時(因爲爲了重新格式化日期而忽略它們)的結果。

我不確定這是一個很好的解決方案,因爲它可能過於嚴格。我沒有真正仔細考慮過它。但無論如何,這是一個想法。


the documentation of DateFormat.parse(其由SimpleDateFormat繼承):

的方法可以不使用給定的字符串的整個文本 。

此外,從「拋出」中相同的方法的部分:

ParseException的 - 如果的 開始時的指定的字符串不能被解析。

注意這一點:如果我實例以字符串 「YYYY-MM-DD」,那麼它會成功解析字符串 「2011-05-12abcdefg」 一個SimpleDateFormat

SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); 
System.out.println(format.parse("2011-05-12abcdefg")); 

上述輸出(我的機器上):

Thu May 12 00:00:00 CDT 2011 

所以基本上它只是解析,因爲它可以之多。

事實上,這是行爲,即使是setLenient(false),對我來說確實有點奇怪。

+0

那麼,如何解決我的問題,任何線索?***國王'L',哈哈 – MarkJ 2011-05-13 00:49:11

+0

@MarkJ:我發佈了一個想法。不太確定它是不是一個好的... – 2011-05-13 01:17:10

+0

好吧,我一直通過使用reg-ex來解決這個問題,似乎它是一個語言錯誤,因爲它在數字前面接受'l'。 java錯誤 – MarkJ 2011-05-13 02:23:31

-1

我相信發生這種情況的原因是因爲### +在末尾處的字母l是是Java中的有效數字。 'l'表示該值是一個長整數。所以,你發佈的那一年真的是201年5月21日,Java處理這封信。 (試一試切換到M或東西,它應該打破。)

+0

但即時通訊嘗試檢查用戶輸入是否有效,並且201l不是有效的。 :(( – MarkJ 2011-05-13 00:10:37

+0

@MarkJ - 我同意從人的角度來看它是無效的)從語言的角度來看它是有效的你需要做什麼來解決這個特定的問題是在你的解析器中有一個額外的檢查:沒有字母在您的數值(包括dd和yyyy)中添加額外的檢查,它應該可以解決您的問題 – JasCav 2011-05-13 00:13:23

+0

未爆發:http://pastebin.com/HQxbVKzZ – OscarRyz 2011-05-13 00:16:32

0

您可能需要在這裏創建自己的驗證器。由於它如何投射數字,它會給出f和l後的有效日期。

我建議使用String.indexOf的各種迭代來查找「/」的索引位置,然後測試子字符串。至少如何驗證日期的數字部分應該是非常明顯的。你一月二月三月等的使用可能更加複雜,中間確認;)

編輯,以您的評論:

喜歡的東西 - 我看不到在編輯模式下你的問題,所以我在這裏承擔,

String day, month, year; 
int div1, div2; 
div1=yourDateString.indexOf("/"); 
div2=yourDateString.indexOf("/",div1); 
day =yourDateString.substring(0,div1-1); 
month =yourDateString.substring(div1+1,div2-1); 
year =yourDateString.substring(div2+1,yourDateString.length()-1); 

(我從我的手機發帖,所以我沒有完整的編輯器上下文和標點符號是一個痛苦的屁股,所以我希望你能明白,這將留下每個字段的個別字符串以供測試)

+0

好吧,如何正則表達這種格式,09/May/2011,與2011 donot包含任何letteR? – MarkJ 2011-05-13 01:15:10

0

解決此問題的一種方法是使用ParsePosition。

`      String d = "10/31/201lll"; 
        ParsePosition pp = new ParsePosition(0); 
        SimpleDateFormat sdf = new SimpleDateFormat("mm/dd/yyyy"); 
        sdf.setLenient(false); 

        try { 
          System.out.println(sdf.parse(d, pp)); 
          System.out.println(pp.getIndex()); 
          System.out.println(d.length()); 
        } 
        catch(Exception e){ 
          e.printStackTrace(); 
        } 

`

的parsePosition.getIndex()給你的性格是用於解析的最後一個字符之後的索引。將它與輸入字符串的長度進行比較應該會告訴您這是絕對分析還是部分分析。