我有一个输入字符串,它应该是一个格式为 "yyyyMMdd "的日期。(例如今天的日期-20200507)但有时输入字符串可能是一个无效的格式,日期分析器应该给出一个异常(解析异常),但它不是,除了它返回一个日期对象。
当字符串是错误的或字母数字时,示例代码如下。
class Demo {
public static void main(String args[]) throws Exception {
String inputString = "9450524Q";
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd", Locale.ENGLISH);
System.out.println(formatter.parse(inputString));
}}
输出:
Tue Apr 04 00:00:00 IST 9454
我建议你使用java.time,现代Java日期和时间API,来处理你的日期工作。在你的特殊情况下,优势在于你所需要的formatter已经内置,而且它确实会抛出你所要求的异常。
为了演示,我使用了这个辅助方法。
public static void tryToParse(String dateString) {
try {
LocalDate date
= LocalDate.parse(dateString, DateTimeFormatter.BASIC_ISO_DATE);
System.out.println(dateString + " -> " + date);
} catch (DateTimeParseException dtpe) {
System.out.println(dateString + ": " + dtpe.getMessage());
}
}
试用一下
// Valid date
tryToParse("20200507");
// Invalid date value
tryToParse("20210229");
// Text after date
tryToParse("20200623Q");
// Example from question
tryToParse("9450524Q");
输出是:
20200507 -> 2020-05-07 20210229: Text '20210229' could not be parsed: Invalid date 'February 29' as '2021' is not a leap year 20200623Q: Text '20200623Q' could not be parsed, unparsed text found at index 8 9450524Q: Text '9450524Q' could not be parsed at index 6
也请大家欣赏一下精确而有用的异常信息。上一个案例中发生的情况是:9450年和52月被解析出来了,但是由于 4Q
不是有效的两位数日期,就会抛出异常(在验证52是否是有效的月号之前)。
该 SimpleDateFormat
类是一个臭名昭著的麻烦制造者。你已经发现了它的一个核心设计问题,但肯定不是唯一的问题。它所做的是。它解析了4位数的年份9450和2位数的月份52。一年有12个月,但一 SimpleDateFormat
与标准设置并不关心。它把48个月换算成4年,最后在4年后的第4个月。最后4被解析为月日。剩下的文字,则是 Q
,被忽略了。
在我看来,你的例子表现出三个缺陷,即 SimpleDateFormat
:
从JavaDoc的 DateFormat
从中 SimpleDateFormat
直接继承。
默认情况下,解析是宽松的。如果输入的内容不是这个对象的format方法所使用的形式,但仍然可以被解析为日期,那么解析就会成功。客户端可以坚持严格遵守格式,通过调用
setLenient(false)
.