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

Java 中用 long 存时间戳是合理且主流的做法,但它本身不提供“高精度”——它只精确到毫秒。真正需要微秒或纳秒级分析时,不能靠 long 单独扛,而要配合其他机制分层处理。
long 适合毫秒级时间戳,不是高精度万能解
long 类型在时间场景中主要承载毫秒级时间戳,比如 System.currentTimeMillis() 或 Instant.toEpochMilli() 返回的值。它的优势在于:
- 范围足够大:2026 年的时间戳已超 1.7 × 10¹²,远超
int上限,long安全覆盖到公元 292477 年 - 轻量高效:仅占 8 字节,无对象开销,序列化快,数据库(如 MySQL
BIGINT)原生支持 - 跨系统一致:JS 的
Date.now()、Python 的time.time() * 1000、Go 的UnixMilli()都对齐毫秒long
但它无法表示 1 毫秒以内的部分。例如 1749934043123456(微秒级)转成 long 后只剩 1749934043123,末尾 456 微秒被截断。
纳秒/微秒级必须拆解或换类型
真要保留亚毫秒精度,得跳出单个 long 思维:
立即学习“Java免费学习笔记(深入)”;
- 用
Instant+getNano():Instant内部用两个字段存时间——毫秒部分(long)和纳秒偏移(0–999999999),合起来还原完整纳秒时间 - 数据库存纳秒需谨慎:MySQL 的
BIGINT最大支持约 9.2 × 10¹⁸,纳秒时间戳(如1749934043123456789)已接近上限,建议用DECIMAL(20,0)或拆成millis BIGINT + nanos INT两字段 - 避免用
BigDecimal存时间:虽能保精度,但失去时间语义,无法直接做加减、时区转换,JDBC 和 Jackson 也不原生支持
大数值计算别硬算,善用工具类与流
当 long 用于海量时间戳聚合或区间运算(如统计每分钟请求数、滑动窗口最大值),注意效率和安全:
- 优先用
LongStream:比Stream<long></long>少装箱拆箱,适合批量处理时间戳数组、ID 序列等。例如:LongStream.rangeClosed(start, end).count()统计时间范围内事件数 - 原子更新用
LongAdder或LongAccumulator:高频写场景(如实时指标上报)下,比synchronized或volatile long更高效 - 时间差直接减:
long diffMs = end - start是最安全的毫秒差计算,单位统一、无精度损失;若需秒/分/小时,再除以对应常量(1000、60000、3600000)
常见坑与修复建议
很多“精度问题”其实和 long 无关,而是单位或用法错位:
- 前端解析失败:后端传了秒级时间戳(如
1749934043),JSnew Date(1749934043)当成毫秒,结果落在 1970 年。修复:统一传毫秒,或接口文档明确标注单位 - SQL 查询为空:WHERE 条件写
WHERE ts > 1749934043(少三个零),实际应为1749934043000。修复:加注释,或封装TimeUtil.toMillis(LocalDateTime)工具方法 - 跨时区显示不准:用
SimpleDateFormat格式化long时没设时区,输出 UTC 时间。修复:显式调用setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"))


















