问题背景:
项目原来是在JDK1.5的环境下的,需要迁移到JDK1.8上运行。
原来环境下,用户前台输入年份,输入22-2-2格式,后台使用java.sql.Date.valueOf(String date)处理,处理完之后结果为:0022-02-02,会自动补全格式。
但是在JDK1.8的环境下,会报IllegalArgumentException异常。
问题原因:
通过调查,发现JDK1.5和JDK1.8在实现java.sql.Date.valueOf的时候,处理逻辑不同导致的问题出现。具体原因通过源码可以看出:
java.sql.Date.valueOf在JDK1.5和JDK1.8的实现差异
JDK1.5源码:
public static Date valueOf(String s) {
int year;
int month;
int day;
int firstDash;
int secondDash;
if (s == null) throw new java.lang.IllegalArgumentException();
firstDash = s.indexOf('-');
secondDash = s.indexOf('-', firstDash+1);
if ((firstDash > 0) & (secondDash > 0) & (secondDash < s.length()-1)) {
year = Integer.parseInt(s.substring(0, firstDash)) - 1900;
month = Integer.parseInt(s.substring(firstDash+1, secondDash)) - 1;
day = Integer.parseInt(s.substring(secondDash+1));
} else {
throw new java.lang.IllegalArgumentException();
}
return new Date(year, month, day);
}
可以看到只要判断年月日都有数据就不会报IllegalArgumentException异常。
JDK1.8源码:
public static Date valueOf(String s) {
final int YEAR_LENGTH = 4;
final int MONTH_LENGTH = 2;
final int DAY_LENGTH = 2;
final int MAX_MONTH = 12;
final int MAX_DAY = 31;
int firstDash;
int secondDash;
Date d = null;
if (s == null) {
throw new java.lang.IllegalArgumentException();
}
firstDash = s.indexOf('-');
secondDash = s.indexOf('-', firstDash + 1);
if ((firstDash > 0) && (secondDash > 0) && (secondDash < s.length() - 1)) {
String yyyy = s.substring(0, firstDash);
String mm = s.substring(firstDash + 1, secondDash);
String dd = s.substring(secondDash + 1);
if (yyyy.length() == YEAR_LENGTH &&
(mm.length() >= 1 && mm.length() <= MONTH_LENGTH) &&
(dd.length() >= 1 && dd.length() <= DAY_LENGTH)) {
int year = Integer.parseInt(yyyy);
int month = Integer.parseInt(mm);
int day = Integer.parseInt(dd);
if ((month >= 1 && month <= MAX_MONTH) && (day >= 1 && day <= MAX_DAY)) {
d = new Date(year - 1900, month - 1, day);
}
}
}
if (d == null) {
throw new java.lang.IllegalArgumentException();
}
return d;
}
1.8要精准匹配年份的长度必须为4的时候才会正常执行,不是4的时候,就会报IllegalArgumentException异常。
解决方案:
手动写一个DateUtils类,实现JDK1.5中的valueOf方法,全局替换java.sql.Date.valueOf方法即可。