Java 8 时间日期库使用示例(二)

本文翻译:梁开权

在上一个章节中我们使用Java8提供的时间日期库,能更加便捷和灵活的操作时间日期,本章节我们将接着之前的内容继续跟大家分享Java8的时间日期库

如何增加时间里面的小时数

很多时候我们需要增加小时,分或者秒来计算出将来的时间。Java 8不仅提供了不可变且线程安全的类,它还提供了一些更方便的方法譬如plusHours()来替换原来的add()方法。

顺便说一下,这些方法返回的是一个新的LocalTime实例的引用,因为LocalTime是不可变的,可别忘了存储好这个新的引用。

LocalTime time = LocalTime.now();
LocalTime newTime = time.plusHours(2); // 加2个小时
System.out.println("两个小时后是 : " + newTime);
输出 :
两个小时后是 : 22:12:23.501

可以看到当前时间2小时后是22:12:23.501。现在你可以将它和Java中增加或者减少小时的老的方式进行下比较。一看便知哪种方式更好

如何获取1周后的日期

这与前一个获取2小时后的时间的例子类似,这里我们将学会如何获取到1周后的日期。LocalDate是用来表示无时间的日期的,它有一个plus()方法可以用来增加日,星期,或者月,ChronoUnit则用来表示这个时间单位。

由于LocalDate也是不可变的,因此任何修改操作都会返回一个新的实例,因此别忘了保存起来。

LocalDate today = LocalDate.now();
LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS);
System.out.println("今天是 : " + today);
System.out.println("一个星期后是 : " + nextWeek);
输出:
今天是 : 2018-04-01
一个星期后是 : 2018-04-08

可以看到7天也就是一周后的日期是什么。你可以用这个方法来增加一个月,一年,一小时,一分钟,甚至是十年,查看下Java API中的ChronoUnit类来获取更多选项。

一年前后的日期

这是上个例子的续集。上例中,我们学习了如何使用LocalDate的plus()方法来给日期增加日,周或者月,现在我们来学习下如何用minus()方法来找出一年前的那天。

LocalDate previousYear = today.minus(1, ChronoUnit.YEARS);
System.out.println("一年前是 : " + previousYear);
LocalDate nextYear = today.plus(1, YEARS);
System.out.println("一年后是 : " + nextYear);
输出:
一年前是 : 2017-04-01
一年后是 : 2019-04-01

可以看到现在一共有两年,一个是2017年,一个是2019年,分别是2018的前后那年。

在Java 8中使用时钟

Java 8中自带了一个Clock类,你可以用它来获取某个时区下当前的瞬时时间,日期或者时间。

可以用Clock来替代System.currentTimeInMillis()与 TimeZone.getDefault()方法。

// 返回你当前系统中的世界标准时间.
Clock clock = Clock.systemUTC();
System.out.println("Clock : " + clock);
// 返回你当前系统中带有时区的时间
Clock.systemDefaultZone();
System.out.println("Clock : " + clock);
输出:
Clock : SystemClock[Z]
Clock : SystemClock[Asia/Shanghai]

在Java 8中,LocalDate类有一个isBefore()和isAfter()方法可以用来比较两个日期。

如果调用方法的那个日期比给定的日期要早的话,isBefore()方法会返回true。

LocalDate tomorrow = LocalDate.of(2018, 4, 2);
System.out.println("2018-04-02是未来的时间吗?" + tommorow.isAfter(today));
LocalDate yesterday = today.minus(1, DAYS);
System.out.println("2018-03-31是过去的时间吗?" + yesterday.isBefore(today));
输出:
2018-04-02是未来的时间吗?true
2018-03-31是过去的时间吗?true

可以看到在Java 8中进行日期比较非常简单。不需要再用像Calendar这样的另一个类来完成类似的任务了。

在Java 8中处理不同的时区

Java 8不仅将日期和时间进行了分离,同时还有时区。现在已经有好几组与时区相关的类了,比如ZonId代表的是某个特定的时区,而ZonedDateTime代表的是带时区的时间。它等同于Java 8以前的GregorianCalendar类。

使用这个类,你可以将本地时间转换成另一个时区中的对应时间,比如下面这个例子:

// 带有时区的日期和时间
ZoneId zId = ZoneId.of("GMT+8");
LocalDateTime localtDateAndTime = LocalDateTime.now();
ZonedDateTime bj = ZonedDateTime.of(localtDateAndTime, zId );
System.out.println("当前时区的日期和时间 : " + bj);
输出:

当前时区的日期和时间 : 2019-01-05T11:48:18.122+08:00[GMT+08:00]

可以拿它跟之前将本地时间转换成GMT时间的方式进行下比较。顺便说一下,正如Java 8以前那样,对应时区的那个文本可别弄错了,否则你会碰到这么一个异常:

Exception in thread "main" java.time.zone.ZoneRulesException: Unknown time-zone ID: China/Bei_Jing
at java.time.zone.ZoneRulesProvider.getProvider(ZoneRulesProvider.java:272)
at java.time.zone.ZoneRulesProvider.getRules(ZoneRulesProvider.java:227)
at java.time.ZoneRegion.ofId(ZoneRegion.java:120)
at java.time.ZoneId.of(ZoneId.java:403)
at java.time.ZoneId.of(ZoneId.java:351)

如何表示固定的日期

正如MonthDay表示的是某个重复出现的日子的,YearMonth又是另一个组合,它代表的是像信用卡还款日,定期存款到期日,options到期日这类的日期。

你可以用这个类来找出那个月有多少天,lengthOfMonth()这个方法返回的是这个YearMonth实例有多少天,这对于检查2月到底是28天还是29天可是非常有用的。

YearMonth currentYearMonth = YearMonth.now();
System.out.printf("Days in month year %s: %d%n", currentYearMonth, currentYearMonth.lengthOfMonth());
YearMonth creditCardExpiry = YearMonth.of(2018, Month.FEBRUARY);
System.out.printf("你是信用卡在 %s 到期", creditCardExpiry);
输出:
当前年月的最后一天: 2019-01: 31
你是信用卡在 2018-02 到期

如何在Java 8中检查闰年

这并没什么复杂的,LocalDate类有一个isLeapYear()的方法能够返回当前LocalDate对应的那年是否是闰年。如果你还想重复造轮子的话,可以看下这段代码,这是纯用Java编写的判断某年是否是闰年的逻辑。

System.out.print("今年2019是闰年?" + today.isLeapYear()); //直接判断是否闰年
输出:
今年2019是闰年?false

你可以多检查几年看看结果是否正确,最好写一个单元测试来对正常年份和闰年进行下测试。

两个日期之间包含多少天,多少个月

还有一个常见的任务就是计算两个给定的日期之间包含多少天,多少周或者多少年。你可以用java.time.Period类来完成这个功能。在下面这个例子中,我们将计算当前日期与将来的一个日期之前一共隔着几个月。

LocalDate day = LocalDate.of(2018, Month.APRIL, 1);
LocalDate today = LocalDate.now();
Period period = Period.between(day , today);
System.out.println("2018年4月1日距离今天过去了多少个月: " + period.getMonths());
输出:
2018年4月1日距离今天间隔多少个月: 9

可以看到,现在是2019月1月,而2018年愚人节是4月1日,因此中间隔着9个月。

带时区偏移量的日期与时间

在Java 8里面,你可以用ZoneOffset类来代表某个时区,比如印度是GMT或者UTC5:30,你可以使用它的静态方法ZoneOffset.of()方法来获取对应的时区。只要获取到了这个偏移量,你就可以拿LocalDateTime和这个偏移量创建出一个OffsetDateTime。

LocalDateTime datetime = LocalDateTime.of(2018, Month.JANUARY, 14, 19, 30);
ZoneOffset offset = ZoneOffset.of("+05:30");
OffsetDateTime date = OffsetDateTime.of(datetime, offset);
System.out.println("带时区的日期和时间 : " + date);
输出:
带时区的日期和时间 : 2018-01-14T19:30+05:30

可以看到现在时间日期与时区是关联上了。还有一点就是,OffSetDateTime主要是给机器来理解的,如果是给人看的,可以使用ZoneDateTime类。

更多的内容我们可以在下个章节继续探讨

想获取更多技术视频,请前往叩丁狼官网:http://www.wolfcode.cn/openClassWeb_listDetail.html

你可能感兴趣的:(Java 8 时间日期库使用示例(二))