一、概念
討論在Java中檢查一個字串是否包含有效日期的各種方法,包括Java8之前與Java8之后及Apache Commons Validator的解決方案,
二、日期概述
不管是應該還是方法,在接收資料時,我們都必須在處理之前驗證它的有效性,
在輸入日期的情況下我們需要驗證下面幾點:
- 輸入包含有效的日期格式,如MM/DD/YYYY
- 輸入的各個部分都在有效范圍內
- 可以決議為日歷中的有效日期
我們可以用正則運算式來完成上述作業,但是正則在處理各種輸入格式時很復雜且容易出錯,并且還會降低性能,
下面討論各種靈活、穩鍵、高效的日期驗證的方法,
首先我們撰寫一個日期驗證的介面,
public interface DateValidator {
boolean isValid(String dateStr);
}
下面就以不同的方法來實作這個介面,
三、使用DateFormat
Java從一開始就提供了格式化和決議日期的工具,這些功能在抽像類DateFormat和它的實作類SimpleDateFormat中,
讓我們使用DateFormat來實作日期驗證吧,
public class DateValidatorUsingDateFormat implements DateValidator {
private String dateFormat;
public DateValidatorUsingDateFormat(String dateFormat) {
this.dateFormat = dateFormat;
}
@Override
public boolean isValid(String dateStr) {
DateFormat sdf = new SimpleDateFormat(this.dateFormat);
// 使用嚴格的決議
sdf.setLenient(false);
try {
sdf.parse(dateStr);
} catch (ParseException e) {
return false;
}
return true;
}
}
因為DateFormat相關類是執行緒不安全,我們需要為每個方法呼叫創建一個新的實體,下面我們就來寫單元測驗:
public class DateValidatorUsingDateFormatUnitTest {
@Test
public void givenValidator_whenValidDatePassed_ThenTrue() {
DateValidator validator = new DateValidatorUsingDateFormat("MM/dd/yyyy");
assertTrue(validator.isValid("02/28/2019"));
}
@Test
public void givenValidator_whenInvalidDatePassed_ThenFalse() {
DateValidator validator = new DateValidatorUsingDateFormat("MM/dd/yyyy");
assertFalse(validator.isValid("02/30/2019"));
}
}
這是Java 8之前的通常的解決方案,
四、使用LocalDate
Java 8引入了改進的日期和時間API,添加了LocalDate類,只表示日期,這個類是執行緒安全的,
LocalDate提供了兩個表態方法來決議日期,都使用DateTimeFormatter來決議:
public static LocalDate parse(CharSequence text)
// parses dates using using DateTimeFormatter.ISO_LOCAL_DATE
public static LocalDate parse(CharSequence text, DateTimeFormatter formatter)
// parses dates using the provided formatter
下面用這個決議方法來實作日期驗證
public class DateValidatorUsingLocalDate implements DateValidator {
private DateTimeFormatter dateFormatter;
public DateValidatorUsingLocalDate(DateTimeFormatter dateFormatter) {
this.dateFormatter = dateFormatter;
}
@Override
public boolean isValid(String dateStr) {
try {
LocalDate.parse(dateStr, this.dateFormatter);
} catch (DateTimeParseException e) {
return false;
}
return true;
}
}
下面寫單元測驗
public class DateValidatorUsingLocalDateUnitTest {
DateTimeFormatter dateFormatter = DateTimeFormatter.BASIC_ISO_DATE;
DateValidator validator = new DateValidatorUsingLocalDate(dateFormatter);
@Test
public void givenValidator_whenValidDatePassed_ThenTrue() {
assertTrue(validator.isValid("20190228"));
}
@Test
public void givenValidator_whenInValidDatePassed_ThenFalse() {
assertFalse(validator.isValid("20190230"));
}
}

五、使用DateTimeFormater
上一節中LocalDate使用DateTimeFormatter物件進行決議,我們也可以直接使用DateTimeFormatter類進行格式化決議,
DateTimeFormatter分兩個階段決議文本,階段1,它根據配置將日期字串決議為日期和時間欄位,階段2,它將這些日期和時間欄位決議為物件,ResolverStyle控制階段2,它有3個值:
// 結論
// ResolverStyle formatter.parse(text) LocalDate.parse(text, formatter)
// ------------- --------------------- ---------------------------------
// STRICT 6.31,6.32不合理輸出 6.31,6.32拋例外
// SMART 6.31按6.30算 6.32拋例外 同左
// LENIENT 往后延6.31按7.1算 6.32按7.2算 同左
// DateTimeFormatter.ofPatter("yyyy-MM-dd") 是ResolverStyle.SMART模式

下面是直接使用DateTimeFormatter撰寫日期驗證:
public class DateValidatorUsingDateTimeFormatter implements DateValidator {
private DateTimeFormatter dateFormatter;
public DateValidatorUsingDateTimeFormatter(DateTimeFormatter dateFormatter) {
this.dateFormatter = dateFormatter;
}
@Override
public boolean isValid(String dateStr) {
try {
this.dateFormatter.parse(dateStr);
} catch (DateTimeParseException e) {
return false;
}
return true;
}
}
寫測驗
public class DateValidatorUsingDateTimeFormatterUnitTest {
@Test
public void givenValidator_whenValidDatePassed_ThenTrue() {
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd", Locale.SIMPLIFIED_CHINESE)
.withResolverStyle(ResolverStyle.STRICT);
DateValidator validator = new DateValidatorUsingDateTimeFormatter(dateFormatter);
assertTrue(validator.isValid("2019-02-28"));
}
@Test
public void givenValidator_whenInValidDatePassed_ThenFalse() {
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd", Locale.SIMPLIFIED_CHINESE)
.withResolverStyle(ResolverStyle.STRICT);
DateValidator validator = new DateValidatorUsingDateTimeFormatter(dateFormatter);
assertFalse(validator.isValid("2019-02-30"));
}
}
六、使用Apache Commons Validator
Apache Commons專案提供了一個驗證框架,可以驗證日期、時間、數字、貨幣、IP、Email和URL,
本文主要看GenericValidator類,它提供了幾種方法來驗證String是否包含有效日期:
public static boolean isDate(String value, Locale locale)
public static boolean isDate(String value,String datePattern, boolean strict)
要使用這個庫先添加依賴
<dependency>
<groupId>commons-validator</groupId>
<artifactId>commons-validator</artifactId>
<version>1.6</version>
</dependency>
用GenericValidator類來實作日期驗證
assertTrue(GenericValidator.isDate("2019-02-28", "yyyy-MM-dd", true));
assertFalse(GenericValidator.isDate("2019-02-29", "yyyy-MM-dd", true));
七、總結
本文總結了驗證字串是否包含有效日期的幾種方法,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/491862.html
標籤:Java
