前置知识:LocalDateTime类
早在JDK1.0时代,JDK就包含了一个与时间相关的java.util.Date类,而因为其本身的缺陷,其大多数方法都在JDK1.1时代被新引入的与时间相关的Calendar类取代。而Calendar类并不比Date类好太多,其本身也有不少问题。譬如:
对于第二点的代码解释:
Date date = new Date(2077,6,1); // Fri Jul 01 00:00:00 CST 3977
System.out.println(date); // 年份从1990年开始计算:偏移量,月份从0开始,表示9月应该是8
注意存储的年份并不是2077,而是1900+2077;而月份也并不是6月,而是6-1月。这种操作逻辑就与人的直觉产生了冲突。
为了解决上述问题,JDK1.8中新增了许多与时间相关的新的API:今天介绍的DateTimeFormatter类亦是其中之一。
JDK1.8新增的时间日期相关类的实例化都比较“做自己”。
DateTimeFormatter类主要有三种实例化方式,也叫格式化方法:
看不懂没关系,以下将以代码举例说明:
// 1、预定义的标准格式
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
// 2、本地化相关的格式
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);
// 3、自定义的格式
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
以上三种方式都可以获得该类的实例化对象,而各种实例化方式间具体的区别,我们将通过以下部分方法的讲解进行理解。
DateTimeFormatter类的使用上类似于JDK1.8之前的SimpleDateTime类,即对时间日期对象进行格式化或解析。
这里说的记载时间日期的类实质上就是指LocalDateTime类(LocalDate/LocalTime,三个类用法类似,为避免赘述,本文都以最常用的LocalDateTime类进行演示说明)。
该方法的参数是一个接口,而LocalDateTime类实现了这个接口,一般我们调用这个方法都会直接传入一个LocalDateTime类作为参数。返回一个字符串的引用,记录了时间。
LocalDateTime localDateTime = LocalDateTime.now();
String str = dateTimeFormatter.format(localDateTime);
System.out.println(localDateTime); // 2020-06-27T10:09:42.085
System.out.println(str); // 2020-06-27T10:09:42.085
不难发现,预定义的标准格式构造的dateTimeFormatter所进行格式化依据的格式与LocalDateTime默认的toString()打印格式是相同的。我们再看下两外两个。
String str2 = formatter.format(localDateTime);
System.out.println(str2); // {},ISO resolved to 2020-06-23T09:40:22.261
这里打印的格式是本地化相关的格式,就有别之前预定义的标准格式。
接下来看看我们最常用的自定义格式:
String str4 = formatter2.format(localDateTime);
System.out.println(str4); // 2020-06-27 10:22:26
回顾下自定义格式的构造:
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
我们可以发现,formatter2进行格式化所使用的格式实质上就是当初进行构造时我们所传入的以字符串形式(这里是"yyyy-MM-dd hh:mm:ss")所表示的格式。其中y、M、d、h、m、s分别表示年月日时分秒。当然我们也可以随意修改为其他需要的格式,只需要将这些字母重新排列即可。
作为格式化的逆过程,该方法需要传入一个字符序列,并按调用该方法的DateTimeFormatter类实例化对象所储存的格式化方式对传入的字符序列进行解析,最终返回一个TemporalAccessor对象的引用。
TemporalAccessor parse1 = formatter2.parse("2020-06-23 09:50:51");
System.out.println(parse1); // {MilliOfSecond=0, NanoOfSecond=0, SecondOfMinute=51, MinuteOfHour=50, HourOfAmPm=9, MicroOfSecond=0},ISO resolved to 2020-06-23
值得注意的是,parse方法传入的字符串形式一定要与该对象格式化的格式相同,对于预定义的标准格式和本地化相关的格式也是如此规定,否则将会抛出DateTimeParseException。