Java8 新特性连载——全新的时间库(java.time)

Java老鸟肯定针对日期写过DateUtils、DateTool或者DateHelper之类的日期操作工具类,或者用过Apache、Google guava、Joda时间库来进行时间计算,Java8以前JDK内置的时间库真是难用到爆,新入门的童鞋只要考虑一下以下几个需求,然后用Java8之前的API实现一把就能有所体会了:

1、打印出当前时间所在月份的最后一天的日期;

2、计算两个时间间隔时长,如果超过一天就按天数,超过一个小时就按小时数,超过一分钟就按分钟数……

3、给定日期判断出是一年中的第几天?

……

由于日期操作实在太常用了,如果系统中模块多了,如果不加以控制,我敢保证,每个模块都会有一个DateUtils……然后CTO规定统一日期操作库,封装或者规定统一使用Joda或Apache common或google guava,然后由于与数据库可能不一定兼容,还要做一堆转换,真酸爽……

Java8来了,将时间库进行了重新设计,极大的改进了时间操作,兼容性更好,线程安全,使用方便……这个时间库被单独放在java.time包中,其中有几个非常重要的包:我罗列一下,便于童鞋们后期查找相关API:

java.time – 包含值对象的基础包
java.time.chrono – 提供对不同的日历系统的访问
java.time.format – 格式化和解析时间和日期
java.time.temporal – 包括底层框架和扩展特性
java.time.zone – 包含时区支持的类

一、常用的类

再罗列一下我们常用到的类:

LocalDateTime:只存储了日期和时间,如:2017-03-21T14:02:43.455。(后面的.455表示毫秒值的最后三位,使用.withNano(0)可把毫秒值设为0)

LocalDate:只存储了日期,如:2017-03-21。

LocalTime:只存储了时间,如:14:02:43.455。(后面的.455表示毫秒值的最后三位,使用.withNano(0)可把毫秒值设为0)

Year:只表示年份。

Month:只表示月份。

YearMonth:只表示年月。

MonthDay:只表示月日。

Instant:相当于java.util的Date

Clock:它通过指定一个时区,然后就可以获取到当前的时刻,日期与时间。Clock可以替换System.currentTimeMillis()与TimeZone.getDefault()。

Duration:是用来计算两个日期的时间差

注:与老的时间库不一样的地方

*新的库日期与老的一样,1-7,但1代表周一,7代表周日;老的代表周日,7代表周六

*新库中月份从1开始到12,老的从0开始到11

二、Java8时间库对于API的统一命名规范

of:静态工厂方法(用类名去调用)
parse:静态工厂方法,关注于解析(用类名去调用)
now: 静态工厂方法,用当前时间创建实例(用类名去调用)
get:获取某些东西的值
is:检查某些东西的是否是true
with:返回一个部分状态改变了的时间日期对象拷贝(单独一个with方法,参数为TemporalAdjusters类型)
plus:返回一个时间增加了的、时间日期对象拷贝(如果参数是负数也能够有minus方法的效果)
minus:返回一个时间减少了的、时间日期对象拷贝
to:把当前时间日期对象转换成另外一个,可能会损失部分状态
at:把这个对象与另一个对象组合起来,例如: date.atTime(time)
format :根据某一个DateTimeFormatter格式化为字符串

童鞋们在用的时候应该就很容易辨别出想要的API了

三、常见用法

我总结常见的经典用法,其他方法童鞋们可以去挖掘,这个库的东西还是蛮多的,一篇小短文是不足以涵盖全部,也没必要。

1、判断当前是上午或者下午

LocalDateTime now = LocalDateTime.now();
int ampm = now.get(ChronoField.AMPM_OF_DAY);
// ampm=0:上午
// ampm=1:下午

2、获取某个时间的年月日等

LocalDateTime now = LocalDateTime.now();
now.getYear();
now.getMonthValue();
now.getDayOfMonth();
now.getHour();// 24小时制
now.getMinute();
now.getSecond();
now.getNano();

3、时间类的初始化

// 可以指定年、月、日、时、分、秒、毫秒,来自由构造时间
LocalDateTime.of(..);
// 有LocalDateTime之后可以通过with单独设置某个时间属性
dt.withYear(2018);
dt.withMonth(11);

4、时间的计算

LocalDateTime now = LocalDateTime.now();
now.minusDays(3);// 三天前
now.plusHours(2);// 两个小时后
// 时差转换
ZoneOffset offset = ZoneOffset.of("+05:30");
OffsetDateTime date = OffsetDateTime.of(now, offset);
// 也可以通过时区ID来转换
ZoneId america = ZoneId.of("America/New_York");
ZonedDateTime dateAndTimeInNewYork = ZonedDateTime.of(localtDateAndTime, america );

四、我们来看看文章篇头提到的三个问题,我们来看看用Java8怎么来计算:

1、打印出当前时间所在月份的最后一天的日期

now.with(TemporalAdjusters.lastDayOfMonth());
// 以此类推,我们可以得到这个月第一天的日期,当年的第一天、最后一天,下个月的第一天最后一天,明年的第一天最后一天……

2、计算两个时间间隔时长,如果超过一天就按天数,超过一个小时就按小时数,超过一分钟就按分钟数……

LocalDateTime start = LocalDateTime.of(2017, 1, 1, 1, 1);
LocalDateTime end = LocalDateTime.of(2017, 2, 1, 1, 1);
// 计算间隔
Duration result = Duration.between(start, end);
// 间隔天数、小时数、分钟数……
System.out.println(result.toDays()); //31
System.out.println(result.toHours()); //744
System.out.println(result.toMinutes()); //44640
System.out.println(result.toMillis()); //2678400000
System.out.println(result.toNanos()); //2678400000000000

注:Duration.between接受的是Temporal接口哦,所以凡是实现该接口的类都可以用于间隔计算,实现该接口的类库中有好多:

HijrahDate, Instant, JapaneseDate, LocalDate, LocalDateTime, LocalTime, MinguoDate, OffsetDateTime, OffsetTime, ThaiBuddhistDate, Year, YearMonth, ZonedDateTime

3、给定日期判断出是一年中的第几天?

now.getDayOfYear();

五、如何兼容旧的的时间库

未向下兼容,肯定得支持新库与旧库的转换,这个Java设计师们肯定不会马虎,也很简单

Date.toInstant()
Date.from(Instant)
Calendar.toInstant()
发表评论
留言与评论(共有 0 条评论)
   
验证码:

相关文章

推荐文章

'); })();