[英]Make SimpleDateFormat.parse() fail on invalid dates (e.g. month is greater than 12)
我正在使用java.text.SimpleDateFormat
來解析"yyyyMMdd"
形式的字符串。
如果我嘗試解析一個月份大於 12 的字符串,它不會失敗,而是會轉到下一年。 完全可運行的重現:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ParseDateTest {
public static void main(String[] args) throws ParseException {
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
Date result = format.parse("20091504"); // <- should not be a valid date!
System.out.println(result); // prints Thu Mar 04 00:00:00 CST 2010
}
}
我寧願拋出ParseException
。
是否有任何非 hacky 方式強制異常發生? 我的意思是,我不想手動檢查月份是否大於 12。這有點荒謬。
感謝您的任何建議。
注意:我已經知道 Joda Time,但我需要在沒有外部庫的普通 JDK 中完成此操作。
您可以使用 Java 8 時間 API。 例如,如果您使用值為15
的月份:
String strDate = "20091504";
TemporalAccessor ta = DateTimeFormatter.ofPattern("yyyyMMdd").parse(strDate);
你會直接有異常
Exception in thread "main" java.time.format.DateTimeParseException:
Text '20091504' could not be parsed:
Invalid value for MonthOfYear (valid values 1 - 12): 15
通過使用 Java 8 LocalDate
你可以這樣寫,
String strDate = "20091504";
LocalDate date1 = LocalDate.parse(strDate, DateTimeFormatter.BASIC_ISO_DATE);
System.out.println(date1);
這是解析過程中拋出的異常
Exception in thread "main" java.time.format.DateTimeParseException: Text '20091504' could not be parsed: Invalid value for MonthOfYear (valid values 1 - 12): 15
at java.time.format.DateTimeFormatter.createError(Unknown Source)
at java.time.format.DateTimeFormatter.parse(Unknown Source)
at java.time.LocalDate.parse(Unknown Source)
at com.katte.infa.DateFormatDemo.main(DateFormatDemo.java:22)
Caused by: java.time.DateTimeException: Invalid value for MonthOfYear (valid values 1 - 12): 15
at java.time.temporal.ValueRange.checkValidIntValue(Unknown Source)
at java.time.temporal.ChronoField.checkValidIntValue(Unknown Source)
at java.time.chrono.IsoChronology.resolveYMD(Unknown Source)
at java.time.chrono.IsoChronology.resolveYMD(Unknown Source)
at java.time.chrono.AbstractChronology.resolveDate(Unknown Source)
at java.time.chrono.IsoChronology.resolveDate(Unknown Source)
at java.time.chrono.IsoChronology.resolveDate(Unknown Source)
at java.time.format.Parsed.resolveDateFields(Unknown Source)
at java.time.format.Parsed.resolveFields(Unknown Source)
at java.time.format.Parsed.resolve(Unknown Source)
at java.time.format.DateTimeParseContext.toResolved(Unknown Source)
at java.time.format.DateTimeFormatter.parseResolved0(Unknown Source)
... 3 more
使用現代日期時間 API java.time
已經有兩個答案( 1和2 )。 雖然我強烈建議使用第一個,但我寫這個答案是為了澄清兩個重要事實:
DateTimeFormatter.BASIC_ISO_DATE
。 請務必注意,所有預定義的格式化程序都使用ResolverStyle#STRICT
,因此,這是驗證日期字符串的完美模式。DateTimeFormatter
,默認情況下,所有自定義DateTimeFormatter
使用ResolverStyle#SMART
。 這意味着此解決方案可以正確驗證20091504
,因為月份的范圍是從 1 到 12,它無法以所需的方式驗證20090230
之類的字符串。 由於月日的范圍可以從 1 到 31,因此解析器會將其自動更正為2009-02-28
。 使用DateTimeFormatter#withResolverStyle.STRICT
如下所示:
class Main {
public static void main(String[] args) {
String strDate = "20090230";
DateTimeFormatter parserDefaultResStyl = DateTimeFormatter.ofPattern("yyyyMMdd");
DateTimeFormatter parserStrictResStyl = DateTimeFormatter.ofPattern("yyyyMMdd")
.withResolverStyle(ResolverStyle.STRICT);
System.out.println(LocalDate.parse(strDate, parserDefaultResStyl));
try {
System.out.println(LocalDate.parse(strDate, parserStrictResStyl));
} catch (DateTimeException e) {
System.out.println(e.getMessage());
// throw e;
}
}
}
輸出:
2009-02-28
Text '20090230' could not be parsed: Unable to obtain LocalDate from TemporalAccessor: {YearOfEra=2009, DayOfMonth=30, MonthOfYear=2},ISO of type java.time.format.Parsed
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.