java10位时间戳转换:秒级数值怎么读

接口返回一串10位数字,比如 1600000000,你需要在Java里把它变成能读的日期,或者反过来把日期压成这串数字。麻烦往往不在写代码,而在单位:10位是秒,13位是毫秒,弄混一次结果就差了一千倍。下面从实际场景出发,把秒级时间戳的读取、换算和常见坑讲清楚。

在线工具时间戳转换

先确认拿到的是10位还是13位

动手写转换之前,先看数字长度。10位时间戳表示从1970-01-01 00:00:00 UTC起走过的秒数,13位则精确到毫秒。输入10,对应结果是 unix 为 10、milliseconds 为 10000、ISO 写法为 1970-01-01T00:00:10.000Z、UTC 写法为 1970-01-01 00:00:10。可以看到,同一时刻用毫秒表示就是秒数乘以1000。

如果字段名叫 createTime 但长度是13位,却按秒去解析,日期会跑到很远的未来;反过来把10位当毫秒,日期会回到1970年前后。先判断单位,再决定用哪个API,这一步省掉后面大量排查。

用Java把秒级数值变成可读时间

最直接的做法是借助 java.time 包。把10位数值装进 Instant.ofEpochSecond(秒数),再按需要的时区转成 ZonedDateTime,最后用 DateTimeFormatter 输出。整个链路里,秒数进去、秒数出来,不需要手动乘1000,也就避开了单位错误。

如果项目还在用旧的 Date,可以先用秒数乘以1000得到毫秒,再交给 Date 构造器;这一步乘1000要写清楚注释,否则后来的人容易误删。转换完成后,建议拿一个已知值核对,比如输入10应当得到 1970-01-01 00:00:10,对不上就说明时区或单位有问题。需要快速比对时,可以用本站的时间戳转换工具把数值贴进去看结果。

时区差一小时是怎么来的

不少人转换后发现结果比预期早或晚若干小时,这通常不是时间戳错了,而是格式化时用了默认时区。时间戳本身只记录一个绝对时刻,展示成字符串时才需要时区。服务器在UTC、开发机在东八区,同一秒数打印出来就会差一截。

处理办法是显式指定时区,比如 ZoneId.of("Asia/Shanghai") 或 ZoneOffset.UTC,不要依赖系统默认值。日志里同时记录原始秒数和带时区的字符串,排查时能一眼看出是数值问题还是展示问题。

负数和边界值也别忽略

时间戳不总是正数。输入 -650 得到 1969-12-31 23:49:10,输入 -3590 得到 1969-12-31 23:00:10,说明1970年之前的时刻同样可以用秒级数值表达。做校验时如果只允许正整数,就会把这些合法值挡掉。

另外,秒级数值靠近0时变化很快:输入9得到 1970-01-01 00:00:09,输入11得到 1970-01-01 00:00:11,前后只差两秒。写测试用例时挑几个相邻值,能更容易发现四舍五入或截断带来的偏差。想理解不同位数的表现,可以参考10位时间戳转换公式:输入10秒的换算结果里的拆解。

把转换逻辑收进一个工具方法

项目里多处需要转换时,别在每个调用点重复写时区和格式化代码。抽一个方法,入参是 long 秒数和时区,出参是格式化字符串;再配一个反向方法,把日期字符串解析回秒数。方法内部统一处理单位,外部调用者只关心业务含义。

写完补两条断言:一条用输入10校验输出为 1970-01-01 00:00:10,另一条用负数校验1970年前的时间。这样以后有人改实现,测试会第一时间提醒。

总结

处理java10位时间戳转换,核心是先分清秒与毫秒,再用 Instant.ofEpochSecond 或乘1000后的 Date 完成解析,格式化时显式指定时区。转换后用已知值核对,并为1970年前的负数补上测试,基本就能覆盖日常场景。

相关文章

常见问题

Q110位时间戳直接传给 new Date() 为什么不对?

Date 构造器接收的是毫秒。10位是秒,直接传进去会被当成毫秒,结果落在1970年前后。应先乘1000,或改用 Instant.ofEpochSecond。

Q2转换结果和同事的不一致,谁错了?

先看两边用的时区是否相同。时间戳是绝对时刻,格式化字符串才带时区;统一指定 ZoneId 后再比对,通常就能对上。

Q3为什么有的接口返回10位,有的返回13位?

10位精确到秒,13位精确到毫秒,取决于接口设计。拿到数据先判断长度,再决定用秒还是毫秒的解析方式,不要混用。

Q41970年之前的日期能转成10位时间戳吗?

可以,结果是负数。例如 -650 对应 1969-12-31 23:49:10。校验逻辑不要只允许正数,否则会误判。