第七章:Java 8新特性
7.3 新的日期与时间API
7.3.1 为什么需要新的日期与时间API?
在Java 8之前,Java的日期和时间处理主要依赖于java.util.Date和java.util.Calendar类。然而,这些类存在以下问题:
- 线程不安全:
Date和Calendar类的实例是可变的,容易在多线程环境下引发问题。 - 设计混乱:
Date类既包含日期又包含时间,而Calendar类的API设计不够直观。 - 时区处理复杂:时区转换和本地化支持较弱。
- 扩展性差:难以支持新的日期和时间计算需求。
为了解决这些问题,Java 8引入了全新的日期与时间API,位于java.time包中。
7.3.2 核心类介绍
Java 8的日期与时间API提供了以下核心类:
1. LocalDate
- 表示不带时间的日期(年、月、日)。
- 示例:
LocalDate today = LocalDate.now(); // 获取当前日期 LocalDate specificDate = LocalDate.of(2023, 10, 1); // 2023年10月1日
2. LocalTime
- 表示不带日期的时间(时、分、秒、纳秒)。
- 示例:
LocalTime currentTime = LocalTime.now(); // 获取当前时间 LocalTime specificTime = LocalTime.of(14, 30); // 14:30:00
3. LocalDateTime
- 表示日期和时间的组合。
- 示例:
LocalDateTime now = LocalDateTime.now(); // 当前日期和时间 LocalDateTime specificDateTime = LocalDateTime.of(2023, 10, 1, 14, 30);
4. ZonedDateTime
- 表示带时区的日期和时间。
- 示例:
ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
5. Instant
- 表示时间戳(从1970-01-01T00:00:00Z开始的秒和纳秒)。
- 适用于机器时间处理。
- 示例:
Instant instant = Instant.now();
6. Period和Duration
Period:用于计算两个日期之间的间隔(年、月、日)。Duration:用于计算两个时间之间的间隔(时、分、秒、纳秒)。- 示例:
Period period = Period.between(LocalDate.of(2023, 1, 1), LocalDate.now()); Duration duration = Duration.between(LocalTime.of(10, 0), LocalTime.now());
7.3.3 日期与时间的操作
新的API提供了丰富的操作方法,支持链式调用:
1. 加减日期或时间
LocalDate tomorrow = today.plusDays(1);
LocalTime oneHourLater = currentTime.plusHours(1);
2. 修改日期或时间
LocalDate newDate = today.withYear(2024).withMonth(12);
LocalTime newTime = currentTime.withHour(15);
3. 比较日期或时间
boolean isAfter = specificDate.isAfter(today);
boolean isBefore = specificTime.isBefore(currentTime);
7.3.4 格式化与解析
新的API通过DateTimeFormatter类支持日期和时间的格式化和解析:
1. 格式化
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formattedDateTime = LocalDateTime.now().format(formatter);
2. 解析
LocalDateTime parsedDateTime = LocalDateTime.parse("2023-10-01 14:30:00", formatter);
7.3.5 时区处理
新的API通过ZoneId和ZoneOffset类支持时区操作:
1. 获取时区时间
ZonedDateTime shanghaiTime = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
ZonedDateTime newYorkTime = shanghaiTime.withZoneSameInstant(ZoneId.of("America/New_York"));
2. 时区转换
Instant instant = Instant.now();
ZonedDateTime zonedDateTime = instant.atZone(ZoneId.of("Europe/London"));
7.3.6 实际应用示例
1. 计算两个日期之间的天数
long daysBetween = ChronoUnit.DAYS.between(startDate, endDate);
2. 判断是否为闰年
boolean isLeapYear = LocalDate.now().isLeapYear();
3. 获取某月的最后一天
LocalDate lastDayOfMonth = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth());
7.3.7 总结
Java 8的新日期与时间API解决了旧API的诸多问题,提供了更清晰、更易用且线程安全的日期和时间处理方式。通过java.time包中的类,开发者可以轻松完成日期计算、时区转换、格式化等常见操作。建议在新项目中优先使用这些新API。
