Long类型仅支持毫秒级精度,无法表示微秒或纳秒;高精度时间需结合Instant.getNano()等方案分层处理,而非依赖long本身。

Long 类型本身不支持“高精度时间”——它只负责存一个毫秒级整数,精度固定为 1 毫秒,无法表达微秒、纳秒等更细粒度的时间。所谓“高精度时间分析”,关键不在 long 本身,而在于你用它做什么、怎么用、后续如何处理。
long 是时间戳的载体,不是精度来源
Java 中的 System.currentTimeMillis() 返回的是自 1970-01-01 00:00:00 GMT 起的毫秒数,类型为 long。这个值本质是离散的整数,每毫秒跳一次,没有小数部分。它不丢失精度,但天然上限就是毫秒级。
- 它不能表示 “2026-06-15 04:47:23.123456” 中的后三位微秒(123456)
- 如果你从数据库或外部系统拿到一个带微秒的 timestamp(如 1749934043123456),直接转成 long 会截断末尾,只剩 1749934043123(毫秒),损失 456 微秒
- MySQL 的 BIGINT 存 long 时间戳没问题,但若字段本意是纳秒级(如 1749934043123456789),就必须用 DECIMAL(20,0) 或拆成两字段,否则溢出或截断
需要更高精度?换类型,别硬扛
真要微秒/纳秒级时间分析(比如性能压测、日志打点、金融事件排序),必须跳出 long:
-
Instant + nano:Java 8+ 推荐方式。
Instant.now().toEpochMilli()得 long 毫秒;Instant.now().getNano()补足纳秒部分(0–999999999),两者结合可还原完整纳秒时间 - java.time.LocalDateTime / ZonedDateTime:适合业务逻辑中做时区感知的计算,底层仍依赖 long + 纳秒,但 API 更安全、不易出错
- 避免 BigDecimal 存时间:虽然能存任意精度数字,但时间语义混乱,无法直接参与日期加减、时区转换,也不被 JDBC、Jackson 等主流框架原生支持
long 时间戳常见误用与修复
很多“精度问题”其实不是 long 的锅,而是用法不当:
-
前端 JS 解析失败:JavaScript 的
Date构造函数接受毫秒 long,但如果后端传的是秒级(如 1749934043),JS 会当成毫秒,导致时间错乱成 1970 年。修复:统一传毫秒,或明确标注单位 -
MySQL 查询不准:建表用
BIGINT存毫秒没问题,但写 WHERE 条件时写成WHERE event_time > 1749934043(少三个零),结果查不到数据。修复:加单位注释,或封装工具类生成标准时间戳 -
跨时区显示错误:用 long +
SimpleDateFormat格式化时没设时区,导致输出 UTC 时间而非本地时间。修复:显式调用format.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"))
总结:long 用对了,就是最稳的时间基座
它轻量、高效、序列化友好、数据库兼容性好。高精度需求 ≠ 高精度存储,而是分层处理:底层用 long 做可靠锚点,上层按需叠加纳秒、时区、格式化逻辑。别试图让 long 承担它设计之外的责任,也别因误解而弃用它——多数业务场景,毫秒级时间戳已绰绰有余。

















