System.currentTimeMillis() 返回自1970年1月1日00:00:00 UTC起的毫秒数,是线程安全的长整型时间戳,用于Date转换、Instant构建、耗时统计等,但不适用于绝对时刻判断或跨时区直接显示。

System.currentTimeMillis() 返回的是自 1970 年 1 月 1 日 00:00:00 UTC 起经过的毫秒数,是一个简单、轻量、线程安全的长整型数值。它本身不带时区、不具语义,但与 Java 中的日期时间类库(如 java.util.Date、java.time 系列)配合使用时,是构建时间逻辑的基础起点。
与 java.util.Date 的直接转换
java.util.Date 的构造方法和 getTime() 方法都基于毫秒值,因此与 currentTimeMillis() 天然契合:
- 创建当前时间:
new Date(System.currentTimeMillis()) - 还原为毫秒值:
date.getTime()—— 结果与生成它的currentTimeMillis()值一致(忽略极短执行延迟) - 注意:
Date内部存储的就是这个毫秒值,其toString()输出会按 JVM 默认时区格式化,容易引发误解,实际值与时区无关
作为 java.time 类型的起点
java.time 是推荐的现代时间 API,它不直接接受毫秒值构造,但可通过标准方式桥接:
- 转为
Instant:Instant.ofEpochMilli(System.currentTimeMillis()) - 再结合时区转为本地时间:
instant.atZone(ZoneId.systemDefault())或指定时区如ZoneId.of("Asia/Shanghai") - 若需
LocalDateTime(无时区),应先转ZonedDateTime再截取:zdt.toLocalDateTime();避免直接用Instant转,否则会丢失时区上下文
用于时间差与基准计算
毫秒值最适合做“差值”和“相对计算”,比如耗时统计、缓存过期、重试间隔:
- 记录起始:
long start = System.currentTimeMillis() - 执行操作后:
long elapsed = System.currentTimeMillis() - start - 判断是否超时(如 5 秒):
elapsed > 5000 - 注意:不要用它直接做“未来某个时刻”的绝对判断(如“是否过了下午 3 点”),应转为
LocalTime或ZonedDateTime更可靠
跨时区场景下的注意事项
currentTimeMillis() 本身是 UTC 时间戳,不随本地时区变化。但误用可能导致逻辑偏差:
- 显示给用户的时间,必须通过
ZoneId显式转换,不能依赖系统默认时区(尤其在服务器部署环境不一致时) - 数据库存储建议统一用
Instant或 UTC 毫秒值,读取时再按需转换为业务时区 - 避免混用:例如用
System.currentTimeMillis()和Calendar.getInstance().getTimeInMillis()做比较——后者也返回毫秒值,本质相同,但引入Calendar增加冗余

















