1. 概述
在本篇文章中,我们将深入探讨 Java 8 引入的 DateTimeFormatter
类及其格式化模式。我们还会结合实际使用场景,展示该类的多种用法。
DateTimeFormatter
提供了统一的方式来格式化日期和时间,支持预定义格式或自定义格式,非常适合在应用中保持日期时间展示的一致性。
2. 使用预定义实例的 DateTimeFormatter
✅ DateTimeFormatter
内置了多个符合 ISO 和 RFC 标准的预定义格式。例如,我们可以使用 ISO_LOCAL_DATE
来格式化日期,如 “2018-03-09”:
DateTimeFormatter.ISO_LOCAL_DATE.format(LocalDate.of(2018, 3, 9));
如果需要包含时区偏移量,可以使用 ISO_OFFSET_DATE
,输出如 “2018-03-09-03:00”:
DateTimeFormatter.ISO_OFFSET_DATE.format(LocalDate.of(2018, 3, 9).atStartOfDay(ZoneId.of("UTC-3")));
⚠️ 大部分预定义格式都遵循 ISO-8601 标准,这是国际通用的日期时间表示方式。
不过,还有一个特殊的预定义格式是 RFC_1123_DATE_TIME
,它遵循 RFC-1123 标准(IETF 发布):
DateTimeFormatter.RFC_1123_DATE_TIME.format(LocalDate.of(2018, 3, 9).atStartOfDay(ZoneId.of("UTC-3")));
输出结果为:
Fri, 9 Mar 2018 00:00:00 -0300
有时候我们接收到的是字符串形式的日期,且格式已知,这时就可以使用 parse()
方法进行解析:
LocalDate.from(DateTimeFormatter.ISO_LOCAL_DATE.parse("2018-03-09")).plusDays(3);
这段代码的结果是 2018 年 3 月 12 日的 LocalDate
实例。
3. 使用 FormatStyle
的 DateTimeFormatter
在需要更人性化的日期展示时,我们可以使用 FormatStyle
枚举(FULL, LONG, MEDIUM, SHORT)配合 DateTimeFormatter
:
LocalDate anotherSummerDay = LocalDate.of(2016, 8, 23);
System.out.println(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).format(anotherSummerDay));
System.out.println(DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG).format(anotherSummerDay));
System.out.println(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).format(anotherSummerDay));
System.out.println(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT).format(anotherSummerDay));
输出结果为:
Tuesday, August 23, 2016
August 23, 2016
Aug 23, 2016
8/23/16
对于日期+时间的格式,需要使用 ZonedDateTime
实例,并调用 ofLocalizedDateTime()
方法:
LocalDate anotherSummerDay = LocalDate.of(2016, 8, 23);
LocalTime anotherTime = LocalTime.of(13, 12, 45);
ZonedDateTime zonedDateTime = ZonedDateTime.of(anotherSummerDay, anotherTime, ZoneId.of("Europe/Helsinki"));
System.out.println(
DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL)
.format(zonedDateTime));
输出为:
Tuesday, August 23, 2016 1:12:45 PM EEST
我们也可以反向解析:
ZonedDateTime dateTime = ZonedDateTime.from(
DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL)
.parse("Tuesday, August 23, 2016 1:12:45 PM EET"));
System.out.println(dateTime.plusHours(9));
输出结果为:
2016-08-23T22:12:45+03:00[Europe/Bucharest]
4. 自定义格式的 DateTimeFormatter
虽然预定义格式能满足大多数场景,但有时我们需要更灵活的自定义格式。
4.1. 日期格式
例如,我们想用欧洲常用的格式 dd.MM.yyyy
展示日期:
String europeanDatePattern = "dd.MM.yyyy";
DateTimeFormatter europeanDateFormatter = DateTimeFormatter.ofPattern(europeanDatePattern);
System.out.println(europeanDateFormatter.format(LocalDate.of(2016, 7, 31)));
输出为:
31.07.2016
常用日期格式符号如下:
符号 | 含义 | 示例 |
---|---|---|
u | 年份 | 2004; 04 |
y | 年代 | 2004; 04 |
M/L | 月份 | 7; 07; Jul; July |
d | 日期 | 10 |
⚠️ 注意:格式符号的数量会影响输出。例如,MM
会补零,而 M
则不会。
4.2. 时间格式
时间格式符号如下:
符号 | 含义 | 示例 |
---|---|---|
H | 小时(0-23) | 0 |
m | 分钟 | 30 |
s | 秒 | 55 |
S | 毫秒 | 978 |
n | 纳秒 | 987654321 |
示例:
String timeColonPattern = "HH:mm:ss";
DateTimeFormatter timeColonFormatter = DateTimeFormatter.ofPattern(timeColonPattern);
LocalTime colonTime = LocalTime.of(17, 35, 50);
System.out.println(timeColonFormatter.format(colonTime));
输出为:
17:35:50
若要显示 AM/PM,使用 hh:mm:ss a
:
String timeColonPattern = "hh:mm:ss a";
DateTimeFormatter timeColonFormatter = DateTimeFormatter.ofPattern(timeColonPattern);
LocalTime colonTime = LocalTime.of(17, 35, 50);
System.out.println(timeColonFormatter.format(colonTime));
输出为:
05:35:50 PM
4.3. 时区格式
如果需要显示时区,可以使用 z
:
String newYorkDateTimePattern = "dd.MM.yyyy HH:mm z";
DateTimeFormatter newYorkDateFormatter = DateTimeFormatter.ofPattern(newYorkDateTimePattern);
LocalDateTime summerDay = LocalDateTime.of(2016, 7, 31, 14, 15);
System.out.println(newYorkDateFormatter.format(ZonedDateTime.of(summerDay, ZoneId.of("UTC-4"))));
输出为:
31.07.2016 14:15 UTC-04:00
解析时也需注意格式一致性,否则会抛出 DateTimeParseException
。
4.4. 使用 Locale 的格式化
我们可以结合 Locale
实现本地化格式:
LocalDate date = LocalDate.of(2023, 9, 18);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM dd, yy: EEE").withLocale(Locale.US);
String formattedDate = date.format(formatter);
输出为:
Sep 18, 23: Mon
切换为韩语 Locale:
formatter = DateTimeFormatter.ofPattern("MMM dd, yy: EEE").withLocale(Locale.KOREA);
输出为:
9월 18, 23: 월
4.5. Instant 格式化
DateTimeFormatter.ISO_INSTANT
专门用于格式化 UTC 时间戳:
ZonedDateTime zonedDateTime = ZonedDateTime.of(2021, 02, 15, 0, 0, 0, 0, ZoneId.of("Europe/Paris"));
String formattedZonedDateTime = DateTimeFormatter.ISO_INSTANT.format(zonedDateTime);
输出为:
2021-02-14T23:00:00Z
⚠️ 注意:解析时必须指定时区,否则会抛出异常。
4.6. 本地化模式匹配(Java 19 新特性)
Java 19 引入了 ofLocalizedPattern()
方法,用于根据 Locale 匹配最合适的格式,而不是直接本地化。
⚠️ 该方法可能会抛出异常,如果找不到匹配的格式。
5. 总结
本文介绍了 DateTimeFormatter
的多种使用方式,包括预定义格式、自定义格式、本地化格式等,适用于大多数日期时间处理场景。在实际开发中,掌握这些技巧可以让你更轻松地应对各种格式化需求。✅