这里提供几种主流的方法,并解释它们的区别和最佳实践。

核心方法:使用 Date 的构造函数
最直接、最经典的方法是使用 java.util.Date 类的构造函数,该构造函数接受一个 long 类型的参数。
import java.util.Date;
public class LongToDateExample {
public static void main(String[] args) {
// 假设这个 long 值代表从纪元开始的毫秒数
long timestamp = 1678886400000L; // 2025-03-15 00:00:00 GMT
// 使用 Date(long date) 构造函数进行转换
Date date = new Date(timestamp);
// 打印转换后的 Date 对象
// 注意:Date 的 toString() 方法会自动转换为本地时区
System.out.println("转换后的 Date 对象: " + date);
}
}
输出结果(取决于你的系统时区):
转换后的 Date 对象: Wed Mar 15 08:00:00 CST 2025
解释:
new Date(timestamp)创建了一个Date对象,内部存储的就是这个毫秒数。- 当你调用
date.toString()或date.getTime()时,它会进行相应的转换。 date.toString()会将这个时间点转换为你本地时区的字符串表示。date.getTime()会将Date对象转换回原来的long毫秒值。
现代推荐方法:使用 java.time 包 (Java 8+)
自 Java 8 起,官方引入了新的 java.time 包,它提供了更强大、更易用、更不可变(线程安全)的日期和时间 API。强烈推荐在新项目中使用 java.time。

Instant (最直接)
Instant 类代表时间线上的一个瞬时点,它与 java.util.Date 最相似,也是基于 Unix 纪元(1970-01-01T00:00:00Z)的纳秒数。
import java.time.Instant;
import java.util.Date;
public class ModernLongToDateExample {
public static void main(String[] args) {
long timestamp = 1678886400000L;
// 1. 将 long 转换为 Instant
Instant instant = Instant.ofEpochMilli(timestamp);
// 2. 将 Instant 转换为 java.util.Date (如果需要与旧API交互)
Date date = Date.from(instant);
System.out.println("通过 Instant 转换的 Date: " + date);
}
}
优点:
Instant是java.time的核心类,非常直观。Date.from(instant)是官方提供的转换方法。
ZonedDateTime (处理时区)
如果你需要指定特定的时区,ZonedDateTime 是更好的选择。
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;
public class LongToZonedDateTimeExample {
public static void main(String[] args) {
long timestamp = 1678886400000L;
// 1. 将 long 转换为 Instant
Instant instant = Instant.ofEpochMilli(timestamp);
// 2. 为 Instant 指定时区,"Asia/Shanghai"
ZonedDateTime zonedDateTime = instant.atZone(ZoneId.of("Asia/Shanghai"));
// 3. (可选) 如果仍然需要 java.util.Date
Date date = Date.from(zonedDateTime.toInstant());
System.out.println("指定时区的 ZonedDateTime: " + zonedDateTime);
System.out.println("转换回的 Date: " + date);
}
}
输出结果:

指定时区的 ZonedDateTime: 2025-03-15T08:00+08:00[Asia/Shanghai]
转换回的 Date: Wed Mar 15 08:00:00 CST 2025
解释:
Instant是一个绝对的时间点,不关联任何时区。atZone(ZoneId)将这个绝对时间点与指定的时区(如Asia/Shanghai)结合,得到一个带有时区信息的ZonedDateTime。ZonedDateTime可以方便地格式化为特定时区的字符串,"2025-03-15 08:00:00"。
反向操作:Date 转 long
这个操作也很常见,非常简单:
import java.util.Date;
public class DateToLongExample {
public static void main(String[] args) {
Date date = new Date(); // 获取当前时间
// 使用 Date 对象的 getTime() 方法
long timestamp = date.getTime();
System.out.println("当前时间的 Date 对象: " + date);
System.out.println("转换后的 long 时间戳: " + timestamp);
}
}
使用 java.time 的反向操作:
import java.time.Instant;
import java.util.Date;
public class ModernDateToLongExample {
public static void main(String[] args) {
Date date = new Date();
// 将 Date 转换为 Instant,然后获取 epoch 毫秒
long timestamp = date.toInstant().toEpochMilli();
System.out.println("当前时间的 Date 对象: " + date);
System.out.println("转换后的 long 时间戳: " + timestamp);
}
}
总结与最佳实践
| 场景 | 推荐方法 | 优点 | 缺点 |
|---|---|---|---|
| 新项目 (Java 8+) | java.time.Instant |
API 设计优秀、不可变、线程安全、功能强大 | 不直接兼容旧版 Date API |
| 必须兼容旧代码 | new Date(long) |
简单直接,无需任何转换 | java.util.Date 可变、线程不安全、API 设计有缺陷 |
| 需要处理时区 | java.time.ZonedDateTime |
明确处理时区,避免混淆 | 比 Instant 多一步操作 |
核心要点:
long的含义:始终记住long代表的是自 1970-01-01T00:00:00Z(UTC)以来的毫秒数,这是一个绝对时间点,不包含时区信息。java.util.Date的陷阱:Date对象内部也存储这个毫秒数,但其很多方法(如toString())会使用 JVM 的默认时区进行转换,容易引起混淆。- 拥抱
java.time:对于任何新的 Java 开发,请优先使用java.time包,它更清晰、更强大,是处理日期和时间的未来。
代码示例(完整对比)
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;
public class ComprehensiveExample {
public static void main(String[] args) {
long timestamp = 1678886400000L; // 2025-03-15 00:00:00 UTC
// =======================================================
// 1. 传统方法 (java.util.Date)
// =======================================================
System.out.println("--- 传统方法 ---");
Date dateFromLong = new Date(timestamp);
System.out.println("long -> Date: " + dateFromLong);
System.out.println("Date -> long: " + dateFromLong.getTime());
// =======================================================
// 2. 现代方法 (java.time, Java 8+)
// =======================================================
System.out.println("\n--- 现代方法 ---");
// a) 使用 Instant (无时区)
Instant instant = Instant.ofEpochMilli(timestamp);
System.out.println("long -> Instant: " + instant);
// b) 使用 ZonedDateTime (带时区)
ZonedDateTime zonedDateTimeInShanghai = instant.atZone(ZoneId.of("Asia/Shanghai"));
System.out.println("Instant -> ZonedDateTime (Asia/Shanghai): " + zonedDateTimeInShanghai);
ZonedDateTime zonedDateTimeInNewYork = instant.atZone(ZoneId.of("America/New_York"));
System.out.println("Instant -> ZonedDateTime (America/New_York): " + zonedDateTimeInNewYork);
// c) 从 java.time 转回 java.util.Date (如果需要)
Date dateFromInstant = Date.from(instant);
System.out.println("Instant -> Date: " + dateFromInstant);
}
}
这个例子清晰地展示了如何在不同 API 之间进行转换,以及如何使用 java.time 处理时区问题。
