一次 SimpleDateFormat 引发的惨案(1)
- UID
- 1066743
|
一次 SimpleDateFormat 引发的惨案(1)
引子
最近手头上的项目上了一个新功能,每天早上一到公司,就兴致勃勃地登上服务器去查看日志,“窥视”一下跑的正不正常。今天终于碰到“彩蛋”了:
Invalid Date in Date Math String:'2187-02-31T16:00:00Z'
...
Invalid Date in Date Math String:'0001-09-31T16:00:00Z'
复制代码
这是什么鬼?怎么会有这样的日期?一会穿越到一百年后,一会穿越到原始社会,我想问那时的2月和9月都有31号了么?
场景
冷静~ 我们先来理一理业务场景:我这边调用S团队的服务,接口参数传了String类型的开始日期和结束日期,格式:yyyy-MM-dd。既然报了“Invalid Date ...”错误,那是不是服务方对它们进行解析时出了问题呢?登上对方的服务器看日志去,发现很多 NumberFormatException:
2019-01-10 00:31:22 380 [com.xxx.xxx.xxx.xxx.util.DataTool]-[WARN] 2019-01-09 00:00:00 parse err
java.lang.NumberFormatException: For input string: ".109E2.109E2"
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2043)
at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
at java.lang.Double.parseDouble(Double.java:538)
at java.text.DigitList.getDouble(DigitList.java:169)
at java.text.DecimalFormat.parse(DecimalFormat.java:2056)
at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:2162)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514)
at java.text.DateFormat.parse(DateFormat.java:364)
at com.xxx.xxx.xxx.xxx.util.DataTool.CCTToUTC(DataTool.java:29)
2019-01-10 00:31:22 415 [com.xxx.xxx.xxx.xxx.util.DataTool]-[WARN] 2019-01-10 00:00:00 parse err
java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Long.parseLong(Long.java:601)
at java.lang.Long.parseLong(Long.java:631)
at java.text.DigitList.getLong(DigitList.java:195)
at java.text.DecimalFormat.parse(DecimalFormat.java:2051)
at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1869)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514)
at java.text.DateFormat.parse(DateFormat.java:364)
at com.xxx.xxx.xxx.xxx.util.DataTool.CCTToUTC(DataTool.java:29)
复制代码
嗯,"2019-01-09 00:00:00" 和 “2019-01-10 00:00:00” 是我传过来的参数值,对应开始日期和结束日期。这应该没什么问题。那检查一下 DataTool.java 类 CCTToUTC 这个方法的第29行:
public class DataTool {
private static Logger logger = Logger.getLogger(DataTool.class);
private static SimpleDateFormat dateSdf = new SimpleDateFormat("yyyy-MM-dd");
private static SimpleDateFormat timezoneSdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
public static String CCTToUTC(String timeString) {
try {
Date date = dateSdf.parse(timeString); // 第29行
Calendar calendar = Calendar.getInstance();
Date tgtDate = new Date(date.getTime() - calendar.getTimeZone().getRawOffset());
return timezoneSdf.format(tgtDate);
} catch (Exception e) {
logger.warn(timeString+" parse err", e);
return timezoneSdf.format(new Date());
}
}
}
复制代码
代码很简单,定义全局变量 SimpleDateFormat,在 CCTToUTC(String timeString) 中用它对传入的日期进行解析和格式化。但在第一行 parse 的时候就报错了并被捕获到,而后打印了一行 warn 日志,并返回了当前时间 format 后的时间字符串。这不是我们想要的结果。
我怀疑是不是我传入的时间有问题,于是在本类写了个 main 方法,简单 sout 打印调用该方法后的结果,尝试了几个不同的时间串,发现始终得不到上面那些令我“穿越”的日期。 |
|
|
|
|
|