Instant.now().toEpochMilli() 返回的是从 Unix 纪元(1970-01-01T00:00:00Z)到当前时刻的 UTC 毫秒时间戳,不依赖本地时区,无需转换,系统时钟准确即结果正确。

Instant.now().toEpochMilli() 返回的是什么时间
Instant.now().toEpochMilli() 返回的是从 Unix 纪元(1970-01-01T00:00:00Z)到当前时刻的毫秒数,**它本身就是格林威治标准时间(UTC)的时间戳**,不依赖本地时区。不需要额外转换或“校准”——只要系统时钟准确,结果就是正确的 UTC 毫秒时间戳。
常见错误:误以为要配合 ZoneId 或 LocalDateTime 使用
有人会写 LocalDateTime.now().atZone(ZoneId.of("UTC")).toInstant().toEpochMilli(),这不仅冗余,还可能因系统默认时区或夏令时规则引入隐式偏差。而 Instant.now() 直接基于系统纳秒级时钟(通常由 JVM 通过 OS 获取),是获取 UTC 时间戳最直接、最轻量的方式。
- ✅ 正确且推荐:
Instant.now().toEpochMilli() - ❌ 不必要且有风险:
LocalDateTime.now().atZone(ZoneId.systemDefault()).withZoneSameInstant(ZoneId.of("UTC")).toInstant().toEpochMilli() - ⚠️ 注意:
System.currentTimeMillis()也返回 UTC 毫秒值,但精度低(仅毫秒)、可能被系统时钟回拨影响;Instant.now()基于单调时钟,更可靠
在不同 JDK 版本下的行为差异
JDK 8 引入 Instant,此后所有 LTS 版本(8/11/17/21)中 Instant.now().toEpochMilli() 行为一致。但要注意:
- JDK 8u181+ 和 JDK 9+ 默认启用高精度时钟(如
Clock.systemUTC()),精度可达纳秒级,但toEpochMilli()仍截断到毫秒 - 某些嵌入式或容器环境(如 Alpine Linux + musl libc)若未正确配置 NTP,
Instant.now()可能返回漂移值——这不是 API 问题,而是系统时间本身不准 - 不要用
new Date().getTime()替代,虽然值相同,但Date是遗留类,语义模糊且线程不安全
实际使用中容易忽略的点
多数人只关心“取值”,但真实场景中几个细节常导致线上问题:
- 日志打点或接口时间戳若直接用
Instant.now().toEpochMilli(),要注意是否在长流程中多次调用——每次调用都是独立采样,微秒级差异可能引发排序或幂等判断异常 - 测试时若用
Mockito.mockStatic(Instant.class)模拟,需确保 mock 的now()返回固定值,否则单元测试不稳定 - 跨服务传递该时间戳时,接收方应统一用
Instant.ofEpochMilli(...)解析,避免误用LocalDateTime.parse(...)导致时区错乱
真正关键的不是“怎么写这一行代码”,而是理解它背后的时间模型:Instant 是时间轴上的一个不可变点,没有时区,不参与日历计算——一旦混淆这个前提,后续所有时间逻辑都容易出偏。










