为什么java SimpleDateFormat可以解析带有额外字符的格式化文本?

时间:2014-02-26 06:26:28

标签: java simpledateformat

我正在使用MM-dd-yyyy HH:mm:ss格式从用户输入解析日期字符串,我发现12-20-2012 10:10:10 abcdexxxx也可以被删除。怎么会发生这种情况?这是我的代码:

SimpleDateFormat df = new SimpleDateFormat( "MM-dd-yyyy HH:mm:ss" );
String currColValue = "12-20-2012 10:10:10 abcdexxxx";
try{
    d=df.parse( currColValue );
}catch( ParseException e ){
    System.out.println("Error parsing date: "+e.getMessage());
}

但没有例外,String值被解析为Date。为什么呢?

4 个答案:

答案 0 :(得分:10)

the Javadoc of the parse method

  

解析来自 给定字符串开头的文本以生成日期。 该方法可能不会使用给定字符串的整个文本。

(强调我的)。

与上述评论的含义相反,这与宽松解析无关;相反,只是这个方法并不打算消耗整个字符串。如果你想验证它是否消耗了整个字符串,我想你可以设置一个ParsePosition对象和use the two-arg overload,然后检查ParsePosition以查看它是否被解析到最后字符串。

答案 1 :(得分:2)

检查SimpleDateFormat.parse(String)doc。它清楚地说明了它。

Parses text from the beginning of the given string to produce a date. The method may not use the entire text of the given string.

http://docs.oracle.com/javase/7/docs/api/java/text/DateFormat.html#parse(java.lang.String)

答案 2 :(得分:1)

java.time

我想贡献现代的答案。在现代人Java日期和时间API java.time出来的前一个月就问了这个问题,我们现在都应该使用它。

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd-yyyy HH:mm:ss");
    String currColValue = "12-20-2012 10:10:10 abcdexxxx";
    try {
        LocalDateTime ldt = LocalDateTime.parse(currColValue, formatter);
        // Do something with ldt
    } catch (DateTimeParseException e) {
        System.out.println("Error parsing date and time: " + e.getMessage());
    }

输出:

  

错误分析日期和时间:无法分析文本'12 -20-2012 10:10:10 abcdexxxx',未分析文本位于索引19

与旧的SimpleDateFormat类相反,现代类的parse方法确实坚持解析整个字符串(如果您需要的话,可以仅解析部分字符串) 。还请注意异常消息的准确性和清晰度。顺便说一下,SimpleDateFormat不仅早已过时,而且还非常麻烦。您仅发现它具有许多令人惊讶的问题之一。我建议您不再使用SimpleDateFormatDate

链接: Oracle tutorial: Date Time解释了如何使用java.time

答案 3 :(得分:0)

我想使用重载方法来举例说明上述正确答案

public Date parse(String text, ParsePosition pos);

要解析确切的整个字符串,只需创建一个新的ParsePosition对象(索引为0,指示解析需要从开始开始),将其传递给该方法,并在解析后检查其index属性。 索引是解析结束的地方。如果字符串长度匹配,则字符串从头到尾完全匹配。

这是一个演示它的单元测试

public class DateParseUnitTest {

    @Test
    public void testParse(){
        Date goodDate = parseExact("2019-11-05");
        Date badDate1 = parseExact("foo 2019-11-05");
        Date badDate2 = parseExact("2019-11-05 foo");

        assert(goodDate != null);
        assert(badDate1 == null);
        assert(badDate2 == null);
    }

    @Nullable
    private Date parseExact(@NonNull String text){
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");

        ParsePosition pos = new ParsePosition(0);
        Date date = formatter.parse(text, pos);
        if (pos.getIndex() != text.length())
            return null;

        return date;
    }
}