为何System.currentTimeMillis()计算30天前时间转日期不符合预期?
问题原因及解决方案
哦这个问题我之前踩过一模一样的坑!核心原因是整数溢出,咱们来一步步拆解清楚:
为什么会出错?
你写的1000*60*60*24*30里,所有数字默认都是Java的int类型。先算一下这个乘积的实际值:1000*60=60000 → *60=3600000 → *24=86400000 → *30=2592000000
但Java中int类型的最大值是2147483647(大约21亿),而2592000000已经超过了这个上限,所以会发生整数溢出。溢出后计算出的结果是一个错误的负数(实际值为-1702967296),用当前时间戳减去这个负数,相当于加上一个正数,最终得到的rt自然不是30天前的时间戳,转成日期肯定不对。
怎么解决?
有几种简单可靠的方式:
1. 强制将表达式转为long类型计算
只需要给其中一个数字加上L后缀(表示long类型),这样整个乘法表达式就会自动提升为long类型运算,避免溢出:
long rt = System.currentTimeMillis() - (1000L * 60 * 60 * 24 * 30);
2. 使用Java 8+的java.time类库(推荐)
手动计算毫秒数很容易踩溢出、夏令时、闰年这些坑,用Java官方推荐的时间API更安全易读:
import java.time.Instant; import java.time.Duration; long rt = Instant.now().minus(Duration.ofDays(30)).toEpochMilli();
这种方式还能灵活处理各种时间单位(比如小时、分钟),完全不用自己算毫秒数。
3. 用旧版Calendar类(兼容Java 8之前版本)
如果还在维护老项目,也可以用Calendar来计算:
import java.util.Calendar; Calendar cal = Calendar.getInstance(); cal.add(Calendar.DAY_OF_MONTH, -30); long rt = cal.getTimeInMillis();
内容的提问来源于stack exchange,提问作者Exodus
相关产品推荐
相关产品推荐

