429. Java 日期时间 API - Parsing & Formatting

大家好,今天我们来学习 Java Date-Time API 中非常实用的两个功能:
Parsing(解析字符串为日期时间对象)
Formatting(格式化日期时间对象为字符串)


1. 概念简介

在 Java 8 之后,引入了新的 Date-Time API(java.time 包),我们可以通过 DateTimeFormatter 来实现日期和字符串之间的相互转换:

  • 解析(parse):字符串 → 日期时间对象
  • 格式化(format):日期时间对象 → 字符串

DateTimeFormatter 的特点:

  • 不可变(immutable)
  • 线程安全(thread-safe)
    👉 所以它非常适合定义成 静态常量,在全局复用。

💡 注意:

  • 解析失败时会抛出 DateTimeParseException
  • 格式化失败时会抛出 DateTimeException

2. Parsing —— 解析字符串

2.1 使用默认解析器

如果传入的是 ISO 标准格式(例如 "2025-09-15"),我们可以直接解析:

LocalDate date = LocalDate.parse("2025-09-15");
System.out.println(date);  // 输出: 2025-09-15

这里默认使用的是 ISO_LOCAL_DATE 格式。


2.2 使用预定义格式解析

Java 内置了一些常用的格式,比如 BASIC_ISO_DATEyyyyMMdd):

String input = "19590709";
LocalDate date = LocalDate.parse(input, DateTimeFormatter.BASIC_ISO_DATE);
System.out.println(date);  // 输出: 1959-07-09

2.3 使用自定义格式解析

我们可以通过 DateTimeFormatter.ofPattern() 定义自己的解析规则:

String input = "Jan 3 2003";

try {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM d yyyy");
    LocalDate date = LocalDate.parse(input, formatter);
    System.out.println(date);  // 输出: 2003-01-03
} catch (DateTimeParseException e) {
    System.out.printf("%s is not parsable!%n", input);
}

⚠️ 注意:模式和输入字符串必须严格匹配!

  • "MMM d yyyy""Jan 3 2003"
  • "MMM dd yyyy""Jun 03 2003" ✅,但 "Jun 3 2003" ❌(少了一个 0)

3. Formatting —— 格式化日期时间

格式化是把日期时间对象转换为字符串。
例如,输出带有月份缩写、日、年、小时和分钟:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM d yyyy hh:mm a");

LocalDateTime leaving = LocalDateTime.of(2013, Month.JULY, 20, 19, 30);
ZoneId leavingZone = ZoneId.of("America/Los_Angeles");
ZonedDateTime departure = ZonedDateTime.of(leaving, leavingZone);

String out = departure.format(formatter);
System.out.printf("LEAVING: %s (%s)%n", out, leavingZone);

输出:

LEAVING: Jul 20 2013 07:30 PM (America/Los_Angeles)

3.1 跨时区格式化

如果我们模拟一次航班,从旧金山到东京,耗时 650 分钟(10 小时 50 分钟):

// 到达东京
ZoneId arrivingZone = ZoneId.of("Asia/Tokyo");
ZonedDateTime arrival = departure.withZoneSameInstant(arrivingZone)
                                 .plusMinutes(650);

String arrivalStr = arrival.format(formatter);
System.out.printf("ARRIVING: %s (%s)%n", arrivalStr, arrivingZone);

输出:

ARRIVING: Jul 21 2013 10:20 PM (Asia/Tokyo)

3.2 检查夏令时

某些时区可能启用夏令时(Daylight Saving Time, DST),可以这样判断:

if (arrivingZone.getRules().isDaylightSavings(arrival.toInstant())) {
    System.out.printf("  (%s daylight saving time will be in effect.)%n", arrivingZone);
} else {
    System.out.printf("  (%s standard time will be in effect.)%n", arrivingZone);
}

4. 小结 🎯

功能 方法 可能异常
解析字符串 → 日期时间 parse(CharSequence, DateTimeFormatter) DateTimeParseException
格式化日期时间 → 字符串 format(DateTimeFormatter) DateTimeException
特点 DateTimeFormatter 不可变、线程安全 -

最佳实践

  1. 解析时一定要 try-catch,避免输入不符合预期导致程序崩溃。
  2. 常用格式可以定义成静态常量,提高代码可读性。
  3. 注意模式与字符串要完全一致,尤其是 零填充dd vs d)。

更多推荐