为什么java SimpleDataFormat可以解析带有额外字符的格式化文本?
我正在用MM dd yyyy HH:MM:ss格式解析用户输入的日期字符串,我发现12-20-2012 10:10:10 abcdexxxx也可以是pasred。这怎么会发生?这是我的密码:为什么java SimpleDataFormat可以解析带有额外字符的格式化文本?,java,simpledateformat,Java,Simpledateformat,我正在用MM dd yyyy HH:MM:ss格式解析用户输入的日期字符串,我发现12-20-2012 10:10:10 abcdexxxx也可以是pasred。这怎么会发生?这是我的密码: SimpleDateFormat df = new SimpleDateFormat( "MM-dd-yyyy HH:mm:ss" ); String currColValue = "12-20-2012 10:10:10 abcdexxxx"; try{ d=df.parse( currColVa
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());
}
但是没有例外,字符串值被解析为日期。为什么?每:
解析给定字符串开头的文本以生成日期。该方法不能使用给定字符串的整个文本
强调我的
与上述评论的含义相反,这与宽松解析无关;相反,这只是因为此方法不打算使用整个字符串。如果您希望验证它是否使用了整个字符串,我想您可以设置一个ParsePosition对象,然后检查ParsePosition,看看它是否解析到字符串的末尾。Per:
解析给定字符串开头的文本以生成日期。该方法不能使用给定字符串的整个文本
强调我的
与上述评论的含义相反,这与宽松解析无关;相反,这只是因为此方法不打算使用整个字符串。如果您希望验证它是否使用了整个字符串,我想您可以设置一个ParsePosition对象,然后检查ParsePosition,查看它是否解析到字符串的末尾。检查SimpleDataFormat.parseString文档。它清楚地表明了这一点
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.
检查SimpleDataFormat.parseString文档。它清楚地表明了这一点
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.
java.time
我想提供一个现代的答案。这个问题是在java.time(现代java日期和时间API)问世的前一个月提出的,我们现在都应该使用它
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处找到未分析的文本
与旧的SimpleDataFormat类相反,现代类的解析方法坚持解析整个字符串,如果您需要的话,可以只解析字符串的一部分。另外,请注意异常消息的准确性和清晰度。顺便说一句,SimpleDateFormat不仅早已过时,而且还出了名的麻烦。你只发现了许多令人惊讶的问题中的一个。我建议您不再使用SimpleDateFormat和Date
链接:解释如何使用java.time。java.time
我想提供一个现代的答案。这个问题是在java.time(现代java日期和时间API)问世的前一个月提出的,我们现在都应该使用它
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处找到未分析的文本
与旧的SimpleDataFormat类相反,现代类的解析方法坚持解析整个字符串,如果您需要的话,可以只解析字符串的一部分。另外,请注意异常消息的准确性和清晰度。顺便说一句,SimpleDateFormat不仅早已过时,而且还出了名的麻烦。你只发现了许多令人惊讶的问题中的一个。我建议您不再使用SimpleDateFormat和Date
链接:解释如何使用java.time。我想使用方法重载,通过示例继续提供上述正确答案
public Date parse(String text, ParsePosition pos);
要解析整个字符串,只需创建一个索引为0的新ParsePosition对象,指示解析需要从begin开始,将其传递给方法,并在解析后检查其索引属性。
索引是解析结束的地方。如果与字符串长度匹配,则字符串从头到尾完全匹配
下面是一个单元测试来演示它
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;
}
}
我想用重载方法举例说明上述正确答案
public Date parse(String text, ParsePosition pos);
要解析整个字符串,只需创建一个索引为0的新ParsePosition对象,指示解析需要从begin开始,将其传递给方法,并在解析后检查其索引属性。
索引是解析结束的地方。如果与字符串长度匹配,则字符串从头到尾完全匹配
下面是一个单元测试来演示它
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;
}
}
你看过setLenient吗?看过。我将其设置为false并仍在分析中。您是否查看了setLenient的可能副本?是的。我将其设置为false并仍在分析中。可能重复Yes。现在我们正在使用JDK1.8,我更喜欢使用LocalDate/LocalDateTime/DateTimeFormatter。。。但我不能使用这个版本后,它刚刚发布。是的。现在我们正在使用JDK1.8,我更喜欢使用LocalDate/LocalDateTime/DateTimeFormatter。。。但我不能使用这个版本后,它刚刚发布。