在 Java 中,处理时间的 API 主要有两套:
- 旧版日期时间 API(java.util.Date / java.util.Calendar)
- 新版日期时间 API(java.time 包,JDK8+ 推荐使用)
下面我将分别列出这两类 API 的常用类、是否支持时区、常见方法及推荐用途。

✅ 一、旧版时间 API(java.util)
1. java.util.Date
| 特性 |
描述 |
| 是否包含时区? |
❌ 否(本质是 UTC 时间戳) |
| 常用方法 |
getTime()、setTime(long)、toString()(输出带本地时区) |
| 缺点 |
可变、线程不安全、设计混乱 |
示例:
Date now = new Date();
System.out.println(now); // 输出格式:Sat Apr 05 14:30:00 CST 2025
2. java.util.Calendar
示例:
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DAY_OF_MONTH, 1);
System.out.println(cal.getTime());
3. java.text.SimpleDateFormat
示例:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(sdf.format(new Date()));
✅ 二、新版时间 API(java.time,推荐使用)
JDK8 引入,位于 java.time 包下,设计更合理、线程安全、支持时区、易读性强。
1. Instant ------ 时间戳(UTC)
| 特性 |
描述 |
| 是否包含时区? |
❌ 否 |
| 表示什么? |
UTC 时间戳(从 1970-01-01T00:00:00Z 开始的秒/纳秒) |
| 常用方法 |
now()、ofEpochMilli(long)、plusSeconds() |
| 推荐用途 |
日志记录、唯一 ID、分布式系统时间同步 |
示例:
Instant now = Instant.now(); // 当前 UTC 时间
Instant later = now.plusSeconds(3600); // 1小时后
2. LocalDate / LocalTime / LocalDateTime ------ 不带时区的时间
| 类名 |
是否有时区? |
表示内容 |
常用方法 |
LocalDate |
❌ 否 |
年月日 |
now()、of()、plusDays() |
LocalTime |
❌ 否 |
时分秒 |
now()、of()、plusMinutes() |
LocalDateTime |
❌ 否 |
年月日 + 时分秒 |
now()、of()、plusHours() |
示例:
LocalDate today = LocalDate.now();
LocalDateTime now = LocalDateTime.now();
3. ZonedDateTime / OffsetDateTime ------ 带时区的时间
| 类名 |
是否有时区? |
表示内容 |
常用方法 |
ZonedDateTime |
✅ 是 |
完整带时区的时间(如 Asia/Shanghai) |
now(ZoneId)、withZoneSameInstant() |
OffsetDateTime |
✅ 是 |
偏移时间(如 +08:00) |
now()、toZonedDateTime() |
示例:
ZoneId zone = ZoneId.of("Europe/London");
ZonedDateTime londonTime = ZonedDateTime.now(zone);
// 转换为另一个时区
ZonedDateTime shanghaiTime = londonTime.withZoneSameInstant(ZoneId.of("Asia/Shanghai"));
4. ZoneId / ZoneOffset ------ 时区相关
| 类名 |
描述 |
常用方法 |
ZoneId |
代表一个完整的时区(如 Asia/Shanghai) |
of()、systemDefault() |
ZoneOffset |
代表一个偏移量(如 +08:00) |
ofHours()、UTC |
示例:
ZoneId zone = ZoneId.of("America/New_York");
ZoneOffset offset = ZoneOffset.of("+08:00");
5. Duration / Period ------ 时间差
| 类名 |
描述 |
单位 |
是否支持时区 |
Duration |
时间差(精确到纳秒) |
秒、纳秒 |
❌ 否(基于 Instant) |
Period |
日期差(精确到天) |
天、月、年 |
❌ 否 |
示例:
Duration duration = Duration.between(Instant.now(), Instant.now().plusSeconds(3600));
Period period = Period.between(LocalDate.now(), LocalDate.now().plusDays(5));
示例:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
.withZone(ZoneId.of("UTC"));
String formatted = formatter.format(Instant.now());
🧾 总结对比表
| API 类名 |
是否带时区 |
精度 |
推荐用途 |
是否线程安全 |
Date |
❌ 否(实际是 UTC) |
毫秒 |
兼容旧代码 |
❌ |
Calendar |
✅ 是 |
毫秒 |
日期计算 |
❌ |
SimpleDateFormat |
✅ 是 |
- |
格式化 |
❌ |
Instant |
❌ 否 |
纳秒 |
时间戳 |
✅ |
LocalDate / LocalTime / LocalDateTime |
❌ 否 |
天/小时/分钟 |
本地日期操作 |
✅ |
ZonedDateTime |
✅ 是 |
纳秒 |
带时区时间处理 |
✅ |
OffsetDateTime |
✅ 是 |
纳秒 |
固定偏移时间 |
✅ |
Duration |
❌ 否 |
纳秒 |
时间长度计算 |
✅ |
Period |
❌ 否 |
天/月/年 |
日期长度计算 |
✅ |
DateTimeFormatter |
✅ 是 |
- |
格式化/解析 |
✅ |
✅ 推荐组合用法
| 场景 |
推荐 API 组合 |
| 记录时间戳(日志、ID生成) |
Instant |
| 显示给用户看的时间 |
ZonedDateTime + DateTimeFormatter |
| 日期运算(如"明天"、"下周几") |
LocalDate |
| 跨时区时间转换 |
ZonedDateTime + withZoneSameInstant() |
| 时间差计算(精确到毫秒) |
Duration |
| 日期差计算(按天、月) |
Period |