[Java] DateTimeFormatter类 格式化或解析日期时间介绍与应用

前置知识:LocalDateTime类

背景

早在JDK1.0时代,JDK就包含了一个与时间相关的java.util.Date类,而因为其本身的缺陷,其大多数方法都在JDK1.1时代被新引入的与时间相关的Calendar类取代。而Calendar类并不比Date类好太多,其本身也有不少问题。譬如:

  • Calendar类是可变的,即可以直接修改内部储存的时间值,而日期时间这类属性应更类似于字符串String,具有不可变性才较为合理。
  • Date的起始年份都按1900年开始计算,而Date与Calendar的月份都以0开始计算,这与人的直觉和其他属性的计算方式有冲突,我们称其为偏移量。
  • 我们知道有个SimpleDateFormat类可以对日期进行格式化操作,而这个类只能直接操作Date类,对于后来加入并取代Date类大部分方法的Calendar类并不能直接操作。
  • 上述类都不是线程安全的。

对于第二点的代码解释:

        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. 预定义的标准格式,如:ISO_LOCAL_DATE_TIME
  2. 本地化相关的格式,如:ofLocalizedDateTime(FormatStyle.LONG)
  3. 自定义的格式,如:ofPattern(“yyyy-MM-dd hh:mm:ss”)

看不懂没关系,以下将以代码举例说明:

		// 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类进行演示说明)。

格式化 format(TemporalAccessor temporal):

该方法的参数是一个接口,而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分别表示年月日时分秒。当然我们也可以随意修改为其他需要的格式,只需要将这些字母重新排列即可。

解析 parse(CharSequence text):

作为格式化的逆过程,该方法需要传入一个字符序列,并按调用该方法的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。

你可能感兴趣的:(Java)