Java 提供了多套时间处理 API,从早期的 Date
和 Calendar
到现代的 java.time
包。本文将系统解析各 API 的核心类、使用场景及最佳实践。
传统时间 API (Java 8 之前)
java.util.Date
- 用途:表示特定的瞬间(毫秒精度)
- 问题:
- 月份从 0 开始(0 = 一月,11 = 十二月)
- 年份从 1900 年开始计算
- 非线程安全,大部分方法已过时
- 示例:java
1 2 3 4 5 6
// 创建表示当前时间的 Date 对象 Date now = new Date(); System.out.println(now); // 输出: Mon Mar 31 09:33:00 CST 2025 // 创建特定时间的 Date 对象 Date specificDate = new Date(125, 3, 31); // 2025 年 3 月 31 日 (方法已废弃)
java.util.Calendar
- 用途:日期计算和字段操作
- 问题:
- API 设计复杂(如 Calendar.MONTH)
- 可变对象,非线程安全
- 月份仍从 0 开始
- 示例:java
1 2 3
Calendar cal = Calendar.getInstance(); cal.set(2025, Calendar.SEPTEMBER, 20); cal.add(Calendar.DAY_OF_MONTH, 7); // 增加 7 天
现代时间 API (Java 8+ java.time
包)
核心不可变类
类名 | 描述 | 示例 |
---|---|---|
LocalDate | 日期(无时间) | LocalDate.of(2025,3,31) |
LocalTime | 时间(无日期) | LocalTime.parse("09:33:00") |
LocalDateTime | 日期+时间(无时区) | LocalDateTime.now() |
ZonedDateTime | 带时区的完整日期时间 | ZonedDateTime.now(ZoneId.of("Asia/Shanghai")) |
Instant | 时间戳(UTC 时间) | Instant.now() |
时区处理
ZoneId
:IANA1 时区名(如Asia/Shanghai
)java1 2
Set<String> zoneIds = ZoneId.getAvailableZoneIds(); // 所有可用时区 ZoneId tokyoZone = ZoneId.of("Asia/Tokyo");
ZoneOffset
:固定偏移(如+08:00
)java1
ZoneOffset offset = ZoneOffset.ofHours(8); // UTC+8
时间间隔与周期
Duration
:基于时间的量(秒、纳秒)java1 2
Duration duration = Duration.between(startTime, endTime); Duration towHours = Duration.ofHours(2);
Period
:基于日期的量(年、月、日)java1
Period period = Period.between(LocalDate.now(), LocalDate.now().plusMonths(1));
格式化和解析
DateTimeFormatter
:线程安全的格式化工具
java
|
|
时间调整器(TemporalAdjuster
)
- 预定义调整:如月末、下个周一java
1 2
LocalDate nextMonday = LocalDate.now().with(TemporalAdjusters.next(DayOfWeek.MONDAY)); LocalDate lastDayOfMonth = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth());
示例:给定一个日期,如果是周一、周二、周三,则调整到当周周三;如果是周四、周五、周六、周日,则调整到当周周日。
java
|
|
新旧 API 转换
旧 → 新
java
|
|
新 → 旧
java
|
|
最佳实践与常用操作
时间计算
java
|
|
时区转换
java
|
|
闰年判断
java
|
|
数据库交互
- JDBC 类型映射
Java 类型 | JDBC 类型 |
---|---|
LocalDate | DATE |
LocalTime | Time |
LocalDateTime | TIMESTAMP |
Instant | TIMESTAMP WITH TIME ZONE |
实用工具方法
工作日计算(跳过周末)
java
|
|
时间段重叠检测
java
|
|
注意事项
- 时区陷阱:始终使用 IANA 时区名 (如
Asia/Shanghai
),而非所写(如CST
)。 - 不可变性:所有
java.time
类均为不可变,每次操作返回新对象。 - 性能优化:重用
DateTimeFormatter
实例(避免重复解析模式)
总结
- 优先选择:始终使用
java.time
处理时间,避免传统 API。 - 复杂场景:时区转换、夏令时/冬令时处理使用
ZonedDateTime
和ZoneRules
。 - 扩展性:通过
TemporalAdjuster
实现自定义时间逻辑。
通过掌握现代 Java 时间 API,能够以更简洁、安全的方式处理复杂的日期时间需求。
附录: 常用第三方工具
一些常用的第三方工具均对日期时间有所封装,并提供了很多有用的方法。如果我们在工程中使用这些工具,可以避免重复造轮子。
Apache Commons Lang
Maven 依赖: Apache Commons Lang 3.17.0
xml
|
|
Google Guava
Maven 依赖: Google Guava 33.4.6-jre
xml
|
|
Hutool
Maven 依赖: Hutool 5.8.36
xml
|
|
IANA 时区数据库 (Internet Assigned Numbers Authority Time Zone Database),官网地址:https://www.iana.org/ ↩︎
感谢您的耐心阅读!来选个表情,或者留个评论吧!