【Java8新特性】06 新的日期和时间:LocalDate LocalTime LocalDateTime

时间:2022-07-25
本文章向大家介绍【Java8新特性】06 新的日期和时间:LocalDate LocalTime LocalDateTime,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

Java8 由Oracle在2014年发布,是继Java5之后最具革命性的版本了。 Java8吸收其他语言的精髓带来了函数式编程,lambda表达式,Stream流,新日期时间接口等一系列新特性,学会了这些新特性,可以让你实现高效编码、优雅编码。

(1) Date

java.util.Date类是Jdk 1.0引入的,易用性非常糟糕,比如年份的起始是1900年,月份的起始是0。比如要表示2019年6月18日,创建一个Date实例:

    Date date = new Date(119, 5, 18);

Date类已经不推荐使用了。

(2) Calendar

为了解决Date糟糕的设计,Jdk 1.1 引入了java.util.Calendar类。不幸的是Calendar没有扛起大任,仍然暴露出很多设计缺陷,导致写代码时容易出现问题,比如月份还是从0开始。

由于Date和Calendar推出的时间很接近,造成程序员对使用哪个类感到困惑。

还有一个很大的问题,Date和Calendar都是可变的类,这种设计会导致程序出现各种问题。

Date和Calendar的种种问题导致程序员们纷纷抛弃原生的jdk日期时间库,转投第三方组件如Joda-Time,Java设计者似乎意识到这个问题,在借鉴Joda-Time的基础上终于在Java8版本中加入了新的日期时间包java.time.*

2. Java8 新的日期时间API

(1)日期时间常用类

针对日期和时间,Java8提供了LocalDate, LocalTime, LocalDateTime, Instant等常用类。Instant类是机器容易理解的类,通常以毫秒等整数值对时间进行建模。

创建实例常见操作:

// 当前日期
LocalDate date1 = LocalDate.now();
// 指定日期
LocalDate date2 = LocalDate.of(2019, 6, 18);
LocalDate date3 = LocalDate.of(2019, Month.JULY, 18);

// 当前时间
LocalTime time1 = LocalTime.now();
// 指定时间
LocalTime time2 = LocalTime.of(21, 10, 59);

// 当前日期时间
LocalDateTime dateTime1 = LocalDateTime.now();
// 指定日期时间
LocalDateTime dateTime2 = LocalDateTime.of(2019, 6, 18, 21, 10, 59);

// 当前时间戳
Instant instant1 = Instant.now();
// 指定时间戳
Instant instant2 = Instant.ofEpochMilli(1000000L);

(2)时间计算

可以用plus,minus对时间日期进行操作:

LocalDate today = LocalDate.of(2019, 6, 18);
LocalDate tomorrow = today.plus(1L, ChronoUnit.DAYS);
System.out.println(tomorrow); // output: 2019-06-19
LocalDate yesterday = today.minus(1L, ChronoUnit.DAYS);
System.out.println(yesterday); // output: 2019-06-17

你还可以通过Duration计算两个时间的间隔:

Duration duration = Duration.between(dateTime2, dateTime1);
System.out.println(duration.toHours()); // output: 841

Period通过用来计算两个日期之间的间隔:

Period period = Period.between(date2, date1);
System.out.println(period.toTotalMonths()); // output: 1

Duration和Period还包含了很多实用的方法如from,of等,大家可以自行看源码进行学习。

(3)时间解析和格式化

LocalDate,LocalTime,LocalDateTime都有parse静态方法用来解析给定的时间日期串:

// 时间日期解析
LocalDateTime parsedDateTime = LocalDateTime.parse("2019/06/18 12:11:10",
        DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"));
System.out.println(parsedDateTime); // output: 2019-06-18T12:11:10

时间格式化可以使用java8提供的新类DateTimeFormatter,java8之前的SimpleDateFormat不推荐大家再用了。

// 时间日期格式化
LocalDateTime dateTime = LocalDateTime.now();
// 使用自定义formatter
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println(dateTime.format(formatter)); // output: 2019-07-23 23:09:19
// 使用系统自带formatter
System.out.println(dateTime.format(DateTimeFormatter.ISO_DATE_TIME)); // output: 2019-07-23T23:09:19.31

(4)时区使用方法

java8之前使用java.util.TimeZone类处理时区,java8新增ZoneId替代TimeZone。

ZoneId实例化方法:

ZoneId zoneId = ZoneId.of("Asia/Shanghai");
ZoneId zoneId2 = ZoneId.systemDefault();

老时区对象转化为新时区:

ZoneId zoneId3 = TimeZone.getDefault().toZoneId();

带时区的时间表示方法:

LocalDateTime dateTime2 = LocalDateTime.of(2019, 6, 18, 21, 10, 59);

ZoneId zoneId = ZoneId.of("Asia/Shanghai");
ZonedDateTime zonedDateTime = dateTime2.atZone(zoneId);
// output: 2019-06-18T21:10:59+08:00[Asia/Shanghai]
System.out.println(zonedDateTime);

ZoneId zoneId2 = ZoneId.systemDefault();
ZonedDateTime zonedDateTime2 = dateTime2.atZone(zoneId2);
// output: 2019-06-18T21:10:59+08:00[Asia/Shanghai]
System.out.println(zonedDateTime2);

3. 总结

LocalDate, LocalTime, LocalDateTime, ZoneId之间的关系可以用一张图解释: