Java 解析与格式化,用户希望解析或格式化 Date-Time API 中的类,DateTimeFormatter
类用于创建日期 / 时间格式,可以在解析和格式化中使用。DateTimeFormatter
类提供大量预定义格式化器(predefined formatter),包括常量(如 ISO_LOCAL_DATE
)、模式字母(如 uuuu-MMM-dd
)以及本地化样式(如 ofLocalizedDate(dateStyle)
)。
Java 解析与格式化 问题描述
用户希望解析或格式化 Date-Time API 中的类。
Java 解析与格式化 解决方案
DateTimeFormatter
类用于创建日期 / 时间格式,可以在解析和格式化中使用。
Java 解析与格式化 具体实例
DateTimeFormatter
类提供大量预定义格式化器(predefined formatter),包括常量(如 ISO_LOCAL_DATE
)、模式字母(如 uuuu-MMM-dd
)以及本地化样式(如 ofLocalizedDate(dateStyle)
)。
好在解析和格式化的过程并不复杂。在 Date-Time API 中,所有主要的类均提供 parse
和 format
方法。以 LocalDate
类为例,其 parse
和 format
方法的签名如例 8-28 所示。
例 8-28
LocalDate
类定义的parse
和format
方法
static LocalDate parse(CharSequence text) ➊
static LocalDate parse(CharSequence text, DateTimeFormatter formatter)
String format(DateTimeFormatter formatter)
➊ 使用 ISO_LOCAL_DATE
解析和格式化的应用如例 8-29 所示。
例 8-29 对
LocalDateTime
解析和格式化
LocalDateTime now = LocalDateTime.now();
String text = now.format(DateTimeFormatter.ISO_DATE_TIME); ➊
LocalDateTime dateTime = LocalDateTime.parse(text); ➋
❶ 将 LocalDateTime
格式化为字符串
❷ 将字符串解析为 LocalDateTime
因此,我们可以调整日期 / 时间格式、区域设置等各种参数。部分应用如例 8-30 所示。
例 8-30 对日期进行格式化
LocalDate date = LocalDate.of(2017, Month.MARCH, 13);
System.out.println("Full : " +
date.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)));
System.out.println("Long : " +
date.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG)));
System.out.println("Medium : " +
date.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)));
System.out.println("Short : " +
date.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)));
System.out.println("France : " +
date.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)
.withLocale(Locale.FRANCE)));
System.out.println("India : " +
date.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)
.withLocale(new Locale("hin", "IN"))));
System.out.println("Brazil : " +
date.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)
.withLocale(new Locale("pt", "BR"))));
System.out.println("Japan : " +
date.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)
.withLocale(Locale.JAPAN)));
Locale loc = new Locale.Builder()
.setLanguage("sr")
.setScript("Latn")
.setRegion("RS")
.build();
System.out.println("Serbian: " +
date.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)
.withLocale(loc)));
执行上述程序,输出类似于:10
10有传言说,作者有意选择稀有语种和输出格式,只是为了测试 O’Reilly Media 能否正确打印出相应的结果。不过至少就读者所知,这并非事实。
Full : Monday, March 13, 2017
Long : March 13, 2017
Medium : Mar 13, 2017
Short : 3/13/17
France : lundi 13 mars 2017
India : Monday, March 13, 2017
Brazil : Segunda-feira, 13 de Março de 2017
Japan : 2017 年3 月13 日
Serbian: ponedeljak, 13. mart 2017
由于 parse
和 format
方法分别抛出 DateTimeParseException
和 DateTimeException
,用户可能希望在自己的代码中捕获它们。
我们也可以通过 DateTimeFormatter
类提供的 ofPattern
方法创建自定义格式化器,Javadoc 详细描述了所有可以使用的合法值。ofPattern
方法的应用如例 8-31 所示。
例 8-31 自定义格式化模式
ZonedDateTime moonLanding = ZonedDateTime.of(
LocalDate.of(1969, Month.JULY, 20),
LocalTime.of(20, 18),
ZoneId.of("UTC")
);
System.out.println(moonLanding.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
DateTimeFormatter formatter =
DateTimeFormatter.ofPattern("uuuu/MMMM/dd hh:mm:ss a zzz GG");
System.out.println(moonLanding.format(formatter));
formatter = DateTimeFormatter.ofPattern("uuuu/MMMM/dd hh:mm:ss a VV xxxxx");
System.out.println(moonLanding.format(formatter));
输出如下:
1969-07-20T20:18:00Z[UTC]
1969/July/20 08:18:00 PM UTC AD
1969/July/20 08:18:00 PM UTC +00:00
有关 DateTimeFormatter
类的用途以及各种模式字母的含义,请参见 Javadoc。不过读者无须担心,格式化的过程并不复杂。
接下来,我们通过夏时制(daylight savings time)问题来展示本地化日期 / 时间格式化器的应用。北美东部时区(EST)从 2018 年 3 月 11 日凌晨 2 时起实行夏时制,将时钟调快一小时。那么在 3 月 11 日凌晨 2 时 30 分时,某个地区的日期和时间是多少呢?相关示例如例 8-32 所示。
例 8-32 将时钟调快一小时
ZonedDateTime zdt = ZonedDateTime.of(2018, 3, 11, 2, 30, 0, 0,
ZoneId.of("America/New_York"));
System.out.println(
zdt.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL)));
在本例中,ZonedDateTime.of
方法传入年、月、日、小时、分、秒、纳秒以及时区作为参数。除时区(ZoneId
)外,其他字段均为 int
类型,即无法使用 Month
枚举。
输出如下:
Sunday, March 11, 2018 3:30:00 AM EDT
可以看到,程序将时间从凌晨 2 时 30 分调整为凌晨 3 时 30 分。