需求:因為系統有很多日期格式,所以日期驗證函式的輸入是一個日期文字和一個格式字串。格式字串用的是Java定義的格式(參考地址)。
剛開始寫時,覺得很簡單,直接就寫了下面的代碼。
| 代碼如下 |
複製代碼 |
|
public static boolean isDate(String dttm, String format) {
boolean retValue = false;
if (dttm != null) {
SimpleDateFormat formatter = new SimpleDateFormat(format);
try {
formatter.parse(dttm);
retValue = true;
} catch (ParseException e) {
}
}
return retValue;
} |
寫好之後,一測試,發現2012/12/43這種日期居然也返回True,於是查資料,設定轉化時不進位formatter.setLenient(false);之後好用了,代碼為
| 代碼如下 |
複製代碼 |
|
public static boolean isDate(String dttm, String format) {
boolean retValue = false;
if (dttm != null) {
SimpleDateFormat formatter = new SimpleDateFormat(format);
formatter.setLenient(false);
try {
formatter.parse(dttm);
retValue = true;
} catch (ParseException e) {
}
}
return retValue;
} |
寫到這裡,以為萬事大吉了。但之後的測試卻發現,當日期有分隔字元時,只會轉換前一部分,比如2012/12/43ABCD也會返回True。想了一下,覺得先轉為日期型,再轉為字串,再比較兩者是否相等,但馬上就否決了這個方案,因為客戶要求的是不嚴格的日期形式,如格式為yyyy/MM/dd,輸入2012/1/2也需要驗證通過。然後考慮了一下,覺得先用Regex做一次驗證,然後再驗證是否是日期型。代碼如下
上面的代碼只對應了yMdHmsS,雖然對當時的系統已經足夠了,但還是感覺不太爽,覺得應該有一種通用的方法。於是查Java的API,發現parse方法還有一個帶參數的方法。理解了它的使用方法之後,把代碼改成下面的樣子
| 代碼如下 |
複製代碼 |
|
private static boolean isDate(String dttm, String format) {
if (dttm == null || dttm.isEmpty() || format == null || format.isEmpty()) {
return false;
}
DateFormat formatter = new SimpleDateFormat(format);
formatter.setLenient(false);
ParsePosition pos = new ParsePosition(0);
Date date = formatter.parse(dttm, pos);
if (date == null || pos.getErrorIndex() > 0) {
return false;
}
if (pos.getIndex() != dttm.length()) {
return false;
}
return true;
} |
本來以為這樣應該萬事大吉了,但之後的測試又發現兩個Bug。一個是,當輸入的日期沒有年份(需求是沒有輸入年份是預設當前年份)時,預設取的是1970年,這樣的話,如果當年是閏年的話,2/29號就驗證出錯了;另一個是Java的日期和Oracle的日期大小不同,Oracle好像最大隻支援到9999年,而Java可以有2萬多年。所以代碼又被改成了下面的樣子
| 代碼如下 |
複製代碼 |
|
private static boolean isDate(String dttm, String format) {
if (dttm == null || dttm.isEmpty() || format == null || format.isEmpty()) {
return false;
}
if (format.replaceAll("'.+?'", "").indexOf("y") < 0) {
format += "/yyyy";
DateFormat formatter = new SimpleDateFormat("/yyyy");
dttm += formatter.format(new Date());
}
DateFormat formatter = new SimpleDateFormat(format);
formatter.setLenient(false);
ParsePosition pos = new ParsePosition(0);
Date date = formatter.parse(dttm, pos);
if (date == null || pos.getErrorIndex() > 0) {
return false;
}
if (pos.getIndex() != dttm.length()) {
return false;
}
if (formatter.getCalendar().get(Calendar.YEAR) > 9999) {
return false;
}
return true;
} |