Java8 新特性之日期时间对象及一些其他特性
日期时间对象
关于日期时间的操作可以分为两种:
- 转换:与字符串的互相转换,与时间戳的互相转换
- 计算:计算两个时间点之间的间隔、时间点与时间段的计算(计算下周N、下个月D日、去年M月D日等等)
Java8提供了三个类:LocalDate、LocalTime、LocalDateTime,它们的形式如2020-01-01、12:30:00、2020-01-0112:30:00
创建对象
获取类对象的方法非常非常简单
LocalDatenow=LocalDate.now(); LocalDateld=LocalDate.of(2019,1,1); //获取年月日 now.getYear(); now.getMonthValue();//如果你调用了now.getMonth(),那么它将返回给你一个大写的英文月份单词 now.getDayOfMonth(); //顾名应该思义 getDayOfWeek(); getDayOfYear(); //设置年月日 LocalDateld1=ld.withYear(2021);//2021-01-01 LocalDateld2=ld.withMonth(12);//2019-12-01 LocalDateld3=ld.withDayOfMonth(12);//2019-12-12 //你可能会纳闷,既然是设置,为什么不用单词set呢,而用with //因为,set操作一般是改变调用对象本身,没有返回值; //而with是在调用对象基础上另外创建一个新对象,设置好值后返回,没有改变调用对象 //如果你是那个打破砂锅的孩子,你可能会问:为什么不能改变调用对象? //因为LocalDate是final修饰的(final人称Java界的自宫之刀) //从物理的角度来讲,目前人类无法改变时间(穿越) //如果你有ld.withMonth(13)这种反人类历法的操作,当然是会抛出异常的
LocalTime和LocalDateTime都有类似于LocalDate的方法,这里就不一一列举了(因为我感觉自己越来越像api文档了)
Java8API官方文档直通车
转换
日期时间对象和字符串之间的互相转换:
//LocalDateTime对象->字符串 DateTimeFormatterdtf=DateTimeFormatter.ofPattern("yyyy-MM-ddHH:mm:ss"); LocalDateTimenow=LocalDateTime.now(); StringdateTimeStr=now.format(dtf); System.out.println(dateTimeStr); //字符串->LocalDateTime对象 Stringstr="2022-01-3012:15:20"; LocalDateTimedateTime=LocalDateTime.parse(str,dtf); System.out.println(dateTime);
DateTimeFormatter类还提供一些现成的formatter,比如
DateTimeFormatter.BASIC_ISO_DATE==>DateTimeFormatter.ofPattern("yyyyMMdd") DateTimeFormatter.ISO_LOCAL_DATE==>DateTimeFormatter.ofPattern("yyyy-MM-dd") //更多formatter可以api文档中查询
学习的本质,不在于记住哪些知识,而在于它触发了你的思考。——迈克尔·桑德尔
日期时间和时间戳之间的互相转换:
//LocalDateTime对象->时间戳 LocalDateTimenow=LocalDateTime.now(); //获取系统默认时区 ZoneIdsystemDefaultZoneId=ZoneId.systemDefault(); Instantinstant=now.atZone(systemDefaultZoneId).toInstant(); longtimestamp=instant.toEpochMilli(); System.out.println(timestamp); //时间戳->LocalDateTime对象 longtimestamp2=1578919583784L; Instantinstant2=Instant.ofEpochMilli(timestamp2); LocalDateTimedateTime2=LocalDateTime.ofInstant(instant2,systemDefaultZoneId); System.out.println(dateTime2);
“我不明白为什么要把时间戳搞得这么麻烦!”
另外:java.util.Date与java.time.LocalDateTime之间的转换需要通过Instant实现,它俩都没有提供直接的转换方法
//获取系统默认时区 ZoneIdsystemDefaultZoneId=ZoneId.systemDefault(); //Date转为LocalDateTime Datedate3=newDate(); Instantinstant3=date3.toInstant(); LocalDateTimelocalDateTime3=LocalDateTime.ofInstant(instant3,systemDefaultZoneId); //LocalDateTime转为Date Instantinstant4=now.atZone(systemDefaultZoneId).toInstant(); Datedate4=Date.from(instant4);
还有:LocalDateTime可以由LocalDate和LocalTime组成,也可以拆分成它俩
LocalDatenowLocalDate=LocalDate.now(); LocalTimenowLocalTime=LocalTime.now(); LocalDateTimenowLocalDateTime=LocalDateTime.of(nowLocalDate,nowLocalTime); nowLocalDateTime.toLocalDate(); nowLocalDateTime.toLocalTime();
计算
计算时间点与时间点之间的间隔:
//计算日期时间之间的间隔 LocalTimestartTime=LocalTime.now(); LocalTimeendTime=startTime.plusHours(1).plusMinutes(50); Durationduration=Duration.between(startTime,endTime); //间隔秒数 duration.getSeconds(); //间隔天数 duration.toDays(); //间隔小时数 duration.toHours(); //间隔分钟数 duration.toMinutes();
Duration.between(start,end)的参数可以是LocalDateTime、LocalTime
它只会返回一个整数(舍掉小数后的整数,等同于floor()),不会返回1小时50分钟这样的形式
如果你想要y年M个月d天H小时m分钟s秒这种形式,或许你自己动手组装一下了
//计算日期之间的间隔 LocalDatestartDate=LocalDate.now(); LocalDateendDate=LocalDate.of(2031,1,1); Periodpe=Period.between(startDate,endDate); pe.getYears(); pe.getMonths(); pe.getDays();
时间点与时间段的计算:
publicLocalDateTimeplusYears(longyears){ LocalDatenewDate=date.plusYears(years); returnwith(newDate,time); } publicLocalDateTimeplusMonths(longmonths){ LocalDatenewDate=date.plusMonths(months); returnwith(newDate,time); } publicLocalDateTimeplusWeeks(longweeks){ LocalDatenewDate=date.plusWeeks(weeks); returnwith(newDate,time); } publicLocalDateTimeplusDays(longdays){ LocalDatenewDate=date.plusDays(days); returnwith(newDate,time); } publicLocalDateTimeplusHours(longhours){ returnplusWithOverflow(date,hours,0,0,0,1); } publicLocalDateTimeplusMinutes(longminutes){ returnplusWithOverflow(date,0,minutes,0,0,1); } publicLocalDateTimeplusSeconds(longseconds){ returnplusWithOverflow(date,0,0,seconds,0,1); } publicLocalDateTimeplusNanos(longnanos){ returnplusWithOverflow(date,0,0,0,nanos,1); } publicLocalDateTimeminusYears(longyears){ return(years==Long.MIN_VALUE?plusYears(Long.MAX_VALUE).plusYears(1):plusYears(-years)); } publicLocalDateTimeminusMonths(longmonths){ return(months==Long.MIN_VALUE?plusMonths(Long.MAX_VALUE).plusMonths(1):plusMonths(-months)); } publicLocalDateTimeminusWeeks(longweeks){ return(weeks==Long.MIN_VALUE?plusWeeks(Long.MAX_VALUE).plusWeeks(1):plusWeeks(-weeks)); } publicLocalDateTimeminusDays(longdays){ return(days==Long.MIN_VALUE?plusDays(Long.MAX_VALUE).plusDays(1):plusDays(-days)); } publicLocalDateTimeminusHours(longhours){ returnplusWithOverflow(date,hours,0,0,0,-1); } publicLocalDateTimeminusMinutes(longminutes){ returnplusWithOverflow(date,0,minutes,0,0,-1); } publicLocalDateTimeminusSeconds(longseconds){ returnplusWithOverflow(date,0,0,seconds,0,-1); } publicLocalDateTimeminusNanos(longnanos){ returnplusWithOverflow(date,0,0,0,nanos,-1); }
看吧,加减年数、月数、天数、小时数、分钟数、秒数、毫秒数都有
想怎么用就怎么用,举个小例子:
LocalDateTimenow=LocalDateTime.now(); //30年后的今天(我还要上班,还没退休) LocalDateTimeafter30Years=now.plusYears(30L); System.out.println(after30Years); //347个月后(我就能还清贷款了╥﹏╥) LocalDateTimeafter348Months=now.plusMonths(347L); System.out.println(after348Months); //11天后(就是除夕了) LocalDateTimeafter10Days=now.plusDays(10L); System.out.println(after10Days); //8小时前(我在上班) LocalDateTimebefore8Hours=now.minusHours(8L); System.out.println(before8Hours); //3分钟前(我开始听Letitgo这首歌) LocalDateTimebefore3Before=now.minusMinutes(3L); System.out.println(before3Before); //10秒前(写下下面这条代码) LocalDateTimebefore10Second=now.minusSeconds(10L); System.out.println(before10Second);
其实不用区分什么加减的,也可以用plusXxx做减法,只要传入负数参数就行了
另外这里还有一类需求,比如:
明年的感恩节是哪天?(每年11月的第四个星期四为感恩节)
下周五是哪天?
这就要用到时间校正器TemporalAdjuster
这里容我先介绍一下TemporalAdjuster,它是一个函数式接口,只有一个方法adjustInto
@FunctionalInterface publicinterfaceTemporalAdjuster{ TemporaladjustInto(Temporaltemporal); }
Temporal是一个接口,LocalDateTime、LocalDate、LocalTime都是它的实现类
在LocalDateTime、LocalDate、LocalTime中都有with(TemporalAdjusteradjuster)这个方法用来实现上面提到的另类需求。
//下周五 LocalDateTimenow=LocalDateTime.now(); LocalDateTimenextFriday=now.with(dt->{ //dt是`Temporal`对象,但实质上是调用对象的类型 LocalDateTimedateTime=(LocalDateTime)dt; //非常可惜,没有withDayOfWeek()这个方法,要不然就会非常方便了 intdayOfWeekValue=dateTime.getDayOfWeek().getValue(); intfridayValue=DayOfWeek.FRIDAY.getValue(); returndateTime.plusWeeks(1L) .plusDays(fridayValue-dayOfWeekValue); }); System.out.println(nextFriday); //明年的感恩节(明年11月第四个星期四) LocalDatethanksGivingDay=LocalDate.now().with(t->{ LocalDated=(LocalDate)t; //明年11月1日 LocalDatenewDate=d.plusYears(1L).withMonth(11).withDayOfMonth(1); intdayOfWeekValue=newDate.getDayOfWeek().getValue(); intthursdayValue=DayOfWeek.THURSDAY.getValue(); longplusWeeks=dayOfWeekValue>thursdayValue?4L:3L; returnnewDate.plusWeeks(plusWeeks) .plusDays(thursdayValue-dayOfWeekValue); }); System.out.println(thanksGivingDay);
其实TemporalAdjusters提供了许多TemporalAdjuster对象,就像上一节Stream中Collectors之于Collector一样。
使用TemporalAdjusters能够十分方便的实现上面的需求
//下个周五 LocalDateTimenextFriday=LocalDateTime.now().with(TemporalAdjusters.next(DayOfWeek.FRIDAY)); System.out.println(nextFriday); //明年的感恩节(明年11月第四个星期四) LocalDatedate=LocalDate.now().plusYears(1L).withMonth(11); LocalDatethanksGivingDay=date.with(TemporalAdjusters.dayOfWeekInMonth(4,DayOfWeek.THURSDAY)); System.out.println(thanksGivingDay);
注意:TemporalAdjusters.next(DayOfWeekday)方法返回的是接下来第一个周五,并不是我们一般理解的下周五,比如说:今天2020-01-13(周一),那么返回的就是2020-01-17四天后的周五。
另外TemporalAdjusters并不止提供了上面这2个方法,还有很多其他方法,API文档中给出了足够多的例子,一看就明白了。
建议有兴趣的同学,去阅读一些源码,参考Java8代码逻辑,然后用其他编程语言实现相同的日期时间操作,因为在其他编程中(比如javaScript)也会经常用到日期时间的操作
其他特性
罗列出来表示我知道他们,但不表示我理解他们,所以LetItGo!
接口中的默认方法
接口中的静态方法
Optional类
Optionalop=Optional.of(str);
它是用来标识这个变量有可能为空。
如果一个变量有可能为空,Java8之前我们每次使用这个变量时,都必须判断它是否为空。现在也是!!
Optional并不能避免空指针异常,仅仅是表示标识变量可能为空。打个比方:
前面一条路上埋了地雷,但从表面上完全看不出来,除非我们走一步都扔石头试一下,否则说不准哪一步就炸了。而Optional就是用来标识地雷位置的,我们知道了哪个位置有雷,就会绕着走,从而能够安全通过
另外Optional还提供了一个设置默认值的功能,挺好玩的。
IntegerpageSize=null; //以前我们设置默认值 //pageSize=pageSize==null?10:pageSize; //System.out.println(pageSize); //使用Optional设置默认值 pageSize=Optional.ofNullable(pageSize) .orElse(20); System.out.println(pageSize); //自定义默认值 IntegerdefaultPageSize=Optional.ofNullable(pageSize) .orElseGet(()->{ returnnewInteger(50); });
结语
Java8新特性系列随便到此就结束了。
最最关键的,还是多看Java官方API文档!!
我在想可能我们被矫枉过正了。各种各样技术群最多的回答都是:去问百度!!百度全知道吗?!
说实在的,在今天这个时代,是个人都能在网络上发表文章言论,然后大家再互相转载,假的都能成为真的!
没有经过验证就转载的;在当时有效,现在过时了的;随便在文章中一个转载链接的...比比皆是
总结
以上所述是小编给大家介绍的Java8新特性之日期时间对象及一些其他特性,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。