上一篇文章『Java 的时间日期 API』中,咱们学习了由 Date、Calendar,DateFormat 等组成的「传统时间日期 API」,可是传统的处理接口设计并非很友好,不易使用。终于,Java 8 借鉴第三方优秀开源库 Joda-time,从新设计了一套 API。java
那么本篇文章就来简单学习一下新式的时间日期处理接口。git
Instant 和 Date 同样,表示一个时间戳,用于描述一个时刻,只不过它较 Date 而言,能够描述更加精确的时刻。而且 Instant 是时区无关的。github
Date 最多能够表示毫秒级别的时刻,而 Instant 能够表示纳秒级别的时刻。例如:安全
看看代码:bash
public static void main(String[] args){
//建立 Instant 实例
Instant instant = Instant.now();
System.out.println(instant);
Instant instant1 = Instant.ofEpochSecond(20);
System.out.println(instant1);
Instant instant2 = Instant.ofEpochSecond(30,100);
System.out.println(instant2);
Instant instant3 = Instant.ofEpochMilli(1000);
System.out.println(instant3);
}
复制代码
输出结果:微信
2018-04-23T02:43:10.973Z
1970-01-01T00:00:20Z
1970-01-01T00:00:30.000000100Z
1970-01-01T00:00:01Z
复制代码
能够看到,Instant 和 Date 不一样的是,它是时区无关的,始终是格林零时区相关的,也便是输出的结果始终格林零时区时间。markdown
不一样于 Calendar 既能处理日期又能处理时间,java.time 的新式 API 分离开日期和时间,用单独的类进行处理。LocalDate 专一于处理日期相关信息。工具
LocalDate 依然是一个不可变类,它关注时间中年月日部分,咱们能够经过如下的方法构建和初始化一个 LocalDate 实例:学习
看看代码:spa
public static void main(String[] args){ //构建 LocalDate 实例 LocalDate localDate = LocalDate.now(); System.out.println(localDate); LocalDate localDate1 = LocalDate.of(2017,7,22); System.out.println(localDate1); LocalDate localDate2 = LocalDate.ofYearDay(2018,100); System.out.println(localDate2); LocalDate localDate3 = LocalDate.ofEpochDay(10); System.out.println(localDate3); } 复制代码
输出结果:
2018-04-23
2017-07-22
2018-04-10
1970-01-11
复制代码
须要注意一点,LocalDate 会根据系统中当前时刻和默认时区计算出年月日的信息。
除此以外,LocalDate 中还有大量关于日期的经常使用方法:
这些方法都见名知意,此处再也不赘述。
相似于 LocalDate,LocalTime 专一于时间的处理,它提供小时,分钟,秒,毫微秒的各类处理,咱们依然能够经过相似的方式建立一个 LocalTime 实例。
一样的,LocalTime 默认使用系统默认时区处理时间,看代码:
public static void main(String[] a){ LocalTime localTime = LocalTime.now(); System.out.println(localTime); LocalTime localTime1 = LocalTime.of(23,59); System.out.println(localTime1); LocalTime localTime2 = LocalTime.ofSecondOfDay(10); System.out.println(localTime2); } 复制代码
输出结果:
13:59:03.723
23:59
00:00:10
复制代码
固然,LocalTime 中也一样封装了不少好用的工具方法,例如:
LocalDateTime 类则是集成了 LocalDate 和 LocalTime,它既能表示日期,又能表述时间信息,方法都相似,只是有一部分涉及时区的转换内容,咱们待会说。
不管是咱们的 LocalDate,或是 LocalTime,甚至是 LocalDateTime,它们基本是时区无关的,内部并无存储时区属性,而基本用的系统默认时区。每每有些场景之下,缺少必定的灵活性。
ZonedDateTime 能够被理解为 LocalDateTime 的外层封装,它的内部存储了一个 LocalDateTime 的实例,专门用于普通的日期时间处理。此外,它还定义了 ZoneId 和 ZoneOffset 来描述时区的概念。
ZonedDateTime 和 LocalDateTime 的一个很大的不一样点在于,后者内部并无存储时区,因此对于系统的依赖性很强,每每换一个时区可能就会致使程序中的日期时间不一致。
然后者则能够经过传入时区的名称,使用 ZoneId 进行匹配存储,也能够经过传入与零时区的偏移量,使用 ZoneOffset 存储时区信息。
因此,构建一个 ZonedDateTime 实例有如下几种方式:
看代码:
public static void main(String[] a){ ZonedDateTime zonedDateTime = ZonedDateTime.now(); System.out.println(zonedDateTime); LocalDateTime localDateTime = LocalDateTime.now(); ZoneId zoneId = ZoneId.of("America/Los_Angeles"); ZonedDateTime zonedDateTime1 = ZonedDateTime.of(localDateTime,zoneId); System.out.println(zonedDateTime1); Instant instant = Instant.now(); ZoneId zoneId1 = ZoneId.of("GMT"); ZonedDateTime zonedDateTime2 = ZonedDateTime.ofInstant(instant,zoneId1); System.out.println(zonedDateTime2); } 复制代码
输出结果:
2018-04-23T16:10:29.510+08:00[Asia/Shanghai]
2018-04-23T16:10:29.511-07:00[America/Los_Angeles]
2018-04-23T08:10:29.532Z[GMT]
复制代码
简单解释一下,首先第一个输出应该没什么问题,系统保存当前系统日期和时间以及默认的时区。
第二个小例子,LocalDateTime 实例保存了时区无关的当前日期时间信息,也就是这里的年月日时分秒,接着构建一个 ZonedDateTime 实例并传入一个美国时区(西七区)。你会发现输出的日期时间为西七区的 16 点 29 分。
像这种关联了时区的日期时间就很可以解决那种,换时区致使程序中时间错乱的问题。由于我关联了时区,不管你程序换到什么地方运行了,日期+时区 本就已经惟一肯定了某个时刻,就至关于我在存储某个时刻的时候,我说明了这是某某时区的某某时间,即使你换了一个地区,你也不至于把这个时间按本身当前的时区进行解析并直接使用了吧。
第三个小例子就更加的直接明了了,构建 ZonedDateTime 实例的时候,给定一个时刻和一个时区,而这个时刻值就是相对于给定时区的标准时间所通过的毫秒数。
有关 ZonedDateTime 的其余日期时间的处理方法和 LocalDateTime 是同样的,由于 ZonedDateTime 是直接封装了一个 LocalDateTime 实例对象,因此全部相关日期时间的操做都会间接的调用 LocalDateTime 实例的方法,咱们再也不赘述。
Java 8 的新式日期时间 API 中,DateTimeFormatter 做为格式化日期时间的主要类,它与以前的 DateFormat 类最大的不一样就在于它是线程安全的,其余的使用上的操做基本相似。咱们看看:
public static void main(String[] a){ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss"); LocalDateTime localDateTime = LocalDateTime.now(); System.out.println(formatter.format(localDateTime)); String str = "2008年08月23日 23:59:59"; DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss"); LocalDateTime localDateTime2 = LocalDateTime.parse(str,formatter2); System.out.println(localDateTime2); } 复制代码
输出结果:
2018年04月23日 17:27:24
2008-08-23T23:59:59
复制代码
格式化主要有两种状况,一种是将日期时间格式化成字符串,另外一种则是将格式化的字符串装换成日期时间对象。
DateTimeFormatter 提供将 format 方法将一个日期时间对象转换成格式化的字符串,可是反过来的操做却建议使用具体的日期时间类本身的 parse 方法,这样能够省去类型转换的步骤。
现实项目中,咱们也常常会遇到计算两个时间点之间的差值的状况,最粗暴的办法是,所有幻化成毫秒数并进行减法运算,最后在转换回日期时间对象。
可是 java.time 包中提供了两个日期时间之间的差值的计算方法,咱们一块儿看看。
关于时间差的计算,主要涉及到两个类:
例如:
public static void main(String[] args){ LocalDate date = LocalDate.of(2017,7,22); LocalDate date1 = LocalDate.now(); Period period = Period.between(date,date1); System.out.println(period.getYears() + "年" + period.getMonths() + "月" + period.getDays() + "天"); LocalTime time = LocalTime.of(20,30); LocalTime time1 = LocalTime.of(23,59); Duration duration = Duration.between(time,time1); System.out.println(duration.toMinutes() + "分钟"); } 复制代码
输出结果:
0年9月1天
209分钟
复制代码
显然,年月日的日期间差值的计算使用 Period 类足以,而时分秒毫秒的时间的差值计算则须要使用 Duration 类。
最后,关于 java.time 包下的新式日期时间 API,咱们简单的学习了下,并无深刻到源码实现层次进行介绍,由于底层涉及大量的系统接口,涉及到大量的抽象类和实现类,有兴趣的朋友能够自行阅读 jdk 的源码深刻学习。
文章中的全部代码、图片、文件都云存储在个人 GitHub 上:
(https://github.com/SingleYam/overview_java)
欢迎关注微信公众号:扑在代码上的高尔基,全部文章都将同步在公众号上。