问题复盘
我们系统有个任务订单,在每天的某个时间点生成一个取货时间为xxx的订单,取货时间需要每天生成为当天的,所以每天生成订单的时候会替换取货时间的日期部分(年月日)。
还有一个背景是,我们数据库内存的是Integer,而实际操作时间需要用Long类型。
那么下面我们来看下这段问题代码,你能发现那里出问题了么。
//input:1536748290
private Integer changeDateToCurrentDate(Integer time){
Date date = new Date(time*1000);//转换为毫秒级时间戳
Date now = new Date();
date.setYear(now.getYear());
date.setMonth(now.getMonth());
date.setDate(now.getDate());
return new Long(date.getTime()/1000).intValue();//转换为秒级时间戳
}
......
下面揭晓答案,time*1000会存在溢出。
我们用Integer保存秒级时间戳。
Integer最大值能够支持到2038年,够用了。
System.out.println(new Date(0X7FFFFFFF*(long)1000));
//output:Tue Jan 19 11:14:07 CST 2038
但是我想通过Date对日期进行转换的时候,需要先转换成毫秒级时间戳,然后修改日期后,再除以1000输出秒级时间戳。
那么问题就出现了。
现在的秒级时间戳已经到达10位,Integer.MAX_VALUE=2147483647,所以转换为毫秒时间戳就肯定溢出了。
最终得到的时间戳就会出现日期是对的,时间错乱的问题。
修复这个问题也很简单,jvm不会自动将int*int转换为long,那么我们只需要将其中一个参数强制转换为long即可。
Date date = new Date((long)time*1000);
总结
对Integer或者其他数字类型进行操作时,要注意溢出这个问题。熟记每种数字类型的极限值的量级。
下面是我公众号,大家可以关注下。

网友评论