system.currenttimemillis()返回自1970年1月1日utc起的毫秒时间戳,推荐用java.time api转换:毫秒→字符串用instant.ofepochmilli()配合datetimeformatter.withzone();字符串→毫秒需明确时区,无时区时先localdatetime.parse()再atzone().toinstant().toepochmilli()。

System.currentTimeMillis() 返回的是从 1970 年 1 月 1 日 00:00:00 UTC(即 Unix 纪元)到当前时刻的毫秒数,这是一个标准的 long 类型时间戳。要把它转换成可读的日期时间字符串,或从字符串反向解析为时间戳,关键在于正确使用 java.time API(推荐 Java 8+)或兼容的 SimpleDateFormat(旧版,注意线程安全问题)。
毫秒时间戳 → 标准格式字符串(如 yyyy-MM-dd HH:mm:ss)
使用 Instant 和 DateTimeFormatter 是最简洁、线程安全的方式:
- 先将毫秒值转为
Instant:Instant.ofEpochMilli(timestamp) - 再按需指定时区(如系统默认时区
ZoneId.systemDefault()或固定时区如ZoneId.of("Asia/Shanghai")) - 用
LocalDateTime或ZonedDateTime格式化,推荐后者以保留时区语义
示例代码:
String format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.of("Asia/Shanghai"));String result = format.format(Instant.ofEpochMilli(System.currentTimeMillis()));
字符串 → 毫秒时间戳(反向解析)
注意:必须明确字符串对应的时区,否则容易出错(比如 "2024-05-20 12:00:00" 默认不带时区信息):
- 若字符串含时区(如 "2024-05-20T12:00:00+08:00"),可用
OffsetDateTime.parse()直接转为Instant - 若无时区,需先解析为
LocalDateTime,再结合指定时区转为ZonedDateTime,最后调用.toInstant().toEpochMilli()
示例(无时区字符串):
LocalDateTime ldt = LocalDateTime.parse("2024-05-20 12:00:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));ZonedDateTime zdt = ldt.atZone(ZoneId.of("Asia/Shanghai"));
long timestamp = zdt.toInstant().toEpochMilli();
常见误区与注意事项
- 不要用
new Date(long)+SimpleDateFormat在多线程环境直接复用——SimpleDateFormat非线程安全 - 避免混淆“秒级”和“毫秒级”时间戳:Unix 秒戳是 10 位数字,Java 的
currentTimeMillis()是 13 位毫秒戳 - 数据库常用秒级时间戳(如 MySQL
UNIX_TIMESTAMP()),转换时记得除以 1000 并取整 - 前端 JavaScript 的
Date.now()也是毫秒级,与 Java 完全一致,可直接互通
封装一个轻量工具类(实用参考)
可提供静态方法简化日常操作:
-
format(long ts):默认格式 + 东八区 -
parse(String s):按固定格式解析为毫秒值 -
toSeconds(long ms):毫秒转秒(用于对接秒级接口)
核心逻辑无需第三方依赖,纯 JDK 即可完成,稳定且无兼容风险。











