目录
前言
Java8中引入了两个与日期相关的新类
- Period - 计算两个“日期”间隔的类
- Duration - 计算两个“时间”间隔的类
Period 类与 Duration 类都是一段持续时间的概念,如果需要对比时间,它们就需要一个固定的时间值,所以就需要 LocalDate 类与 Instant 、LocalTime、LocalDateTime类来配合它们使用:
- Period 对应使用 LocalDate ,它们的作用范围域都是日期(年/月/日)
- Duration 对应使用 Instant、LocalTime、LocalDateTime,它们的作用范围域都是时间(天/时/分/秒/毫秒/纳秒)
一、Duration - 计算两个“时间”间隔的类
Duration 表示一个时间段,Duration 包含两部分:seconds 表示秒,nanos 表示纳秒,它们的组合表达了时间长度。
因为 Duration 表示时间段,所以 Duration 类中不包含 now() 静态方法。注意,Duration 不包含毫秒这个属性。
Duration只能处理两个时间类,例如LocalTime, LocalDateTime, ZonedDateTime; 如果传入的是LocalDate,将会抛出异常。
Duration默认输出格式为PTnHnMnS,如PT8H6M12.345S
以PT前缀开头,H:小时 M:分钟 S:秒
当Duration为0时,默认为:PT0S
1.1、Duration常用API:
方法 | 说明 |
---|---|
static Duration between(Temporal startInclusive, Temporal endExclusive) | 计算两个时间的间隔,默认是秒 |
boolean isNegative() | 检查Duration实例是否小于0,若小于0返回true, 若大于等于0返回false |
long toDays() | 将时间转换为以天为单位的long值 |
long toHours() | 将时间转换为以时为单位的long值 |
long toMinutes() | 将时间转换为以分钟为单位的long值 |
long toSeconds() | 将时间转换为以秒为单位的long值 |
long toMillis() | 将时间转换为以毫秒为单位的long值 |
long toNanos() | 将时间转换为以纳秒为单位的long值 |
使用示例:
LocalDateTime start = LocalDateTime.parse("2007-12-03T10:15:30"); LocalDateTime end = LocalDateTime.parse("2007-12-05T10:25:33"); //between的用法是end-start的时间,若start的时间大于end的时间,则所有的值是负的 Duration duration = Duration.between(start, end); String timeString = duration.toString(); //此持续时间的字符串表示形式,使用基于ISO-8601秒*的表示形式,例如 PT8H6M12.345S System.out.println("相差的天数="+duration.toDays()); System.out.println("相差的小时="+ duration.toHours()); System.out.println("相差的分钟="+duration.toMinutes()); System.out.println("相差的秒数="+duration.toSeconds()); System.out.println("相差的毫秒="+duration.toMillis()); System.out.println("相差的纳秒="+duration.toNanos()); System.out.println("timeString时间="+timeString); //isNegative返回Duration实例对象是否为负 System.out.println(Duration.between(start, end).isNegative());//false end-start为正,所以此处返回false System.out.println(Duration.between(end, start).isNegative());//true start-end为负,所以此处返回true System.out.println(Duration.between(start, start).isNegative());//false start-start为0,所以此处为false
执行结果:
相差的天数=2 相差的小时=48 相差的分钟=2890 相差的秒数=173403 相差的毫秒=173403000 相差的纳秒=173403000000000 timeString时间=PT48H10M3S
1.2、计算两个“时间”间隔
方法一:【推荐】通过Duration计算两个LocalTime相差的时间
LocalTime start = LocalTime.parse("10:51:01.167526700"); LocalTime end = LocalTime.parse("15:52:03.167526701"); //between的用法是end-start的时间,若start的时间大于end的时间,则所有的值是负的 Duration duration = Duration.between(start, end); System.out.println("两个时间相差:"+duration.toSeconds()+"秒,相差:"+duration.toHours()+"小时,相差:"+duration.toMinutes()+"分钟");
输出:
两个时间相差:18062秒,相差:5小时,相差:301分钟
方法二:ChronoUnit也可以计算两个单元之间的差值。
我们使用ChronoUnit类的between() 方法来执行相同的操作
LocalTime start = LocalTime.parse("10:51:01.167526700"); LocalTime end = LocalTime.parse("15:52:03.167526701"); long seconds = ChronoUnit.SECONDS.between(start , end ); long hour = ChronoUnit.HOURS.between(start , end ); long minute = ChronoUnit.MINUTES.between(start , end ); System.out.println("两个时间相差:"+seconds+"秒,相差:"+hour+"小时,相差:"+minute+"分钟");
输出:
两个时间相差:18062秒,相差:5小时,相差:301分钟
方法三:调用LocalDateTime类的.until方法,返回 总的相差的年数、月数、天数、时、分、秒
// 代码略(看文章后面的.until方法示例)
方法四:通过LocalTime类的toSecondOfDay()方法,返回时间对应的秒数,然后计算出两个时间相差的间隔
LocalTime start = LocalTime.parse("10:51:01.167526700"); LocalTime end = LocalTime.parse("15:52:03.167526701"); int time = end.toSecondOfDay() - start.toSecondOfDay(); System.out.println("两个时间相差:"+time+"秒");
输出:
两个时间相差:18062秒
1.3、计算两个“时间戳”间隔
项目中经常会有时间戳的值,下面的示例一起看一下如何比较时间戳。
long todayTimeMillis = System.currentTimeMillis(); long yesterdayTimeMillis = todayTimeMillis - 24 * 60 * 60 * 1000; //通过Instant类,可以直接将毫秒值转换为Instant对象 Instant yesterday = Instant.ofEpochMilli(yesterdayTimeMillis); Instant today = Instant.ofEpochMilli(todayTimeMillis); Duration duration = Duration.between(yesterday, today); System.out.println("天数 = "+duration.toDays()); //天数 = 1
二、Period - 计算两个“日期”间隔的类
Period 在概念上和 Duration 类似,区别在于 Period 是以年月日来衡量一个时间段。Duration 用于计算两个时间间隔,Period 用于计算两个日期间隔,所以 between() 方法只能接收 LocalDate 类型的参数。
说明:
Period可以用于计算两个“日期”之间的间隔,但是得到的是年月日,如两个日期相差1年2月3天,但是没办法知道1年2月3天具体是多少天,下面有讲通过调用ChronoUnit.between()方法计算两个单元相差的天数、月数、年数…
Period默认输出格式为PnYnMnD,如P2021Y12M3D
以P前缀开头,Y:年 M:月份 D:天
当Period为0时,默认为:P0D
2.1、Period常用API:
方法 | 说明 |
---|---|
static Period between(LocalDate startDateInclusive, LocalDate endDateExclusive) | 计算两个日期之间的间隔 |
boolean isNegative() | 检查此时间段的三个单位中是否有一个为负数。这将检查年,月或天的单位是否小于零。如果此期间的任何单位为负,则为true |
int getYears() | 获取年 |
int getMonths() | 获取月 |
int getDays() | 获取日 |
Period p = Period.of(2021, 12, 3); System.out.println("年月日:"+p); p = Period.ofYears(1); System.out.println("年:"+p); p = Period.ofWeeks(2); System.out.println("周的天数"+p); Period period = Period.of(2021,-1,8); System.out.println("校验年月日任何一位值是否有负数:{}",period.isNegative());//true
输出:
年月日:P2021Y12M3D 年:P1Y 周的天数P14D
注意
- getYears()、getMonths()、getDays()只能输出Period中的年月日。像如下的示例,想知道两个日期相差多少天需要用ChronoUnit.between()方法。
LocalDate start = LocalDate.of(2020,2,28); LocalDate end = LocalDate.of(2021,12,3); Period period = Period.between(start,end); System.out.println("两个时间之间的差值 年:"+period.getYears()+",月:"+period.getMonths()+",日:"+period.getDays());
输出:
两个时间之间的差值 年:1,月:9,日:5
2.2、计算两个日期相差的具体天数
方法一:ChronoUnit也可以计算两个单元之间的天数、月数或年数。
我们使用ChronoUnit类的between() 方法来执行相同的操作:
LocalDate start = LocalDate.of(2020,2,28); LocalDate end = LocalDate.of(2021,12,3); long seconds = ChronoUnit.DAYS.between(start , end ); // 结果:644 long month= ChronoUnit.MONTHS.between(start , end ); // 结果:21 long year= ChronoUnit.YEARS.between(start , end ); // 结果:1
方法二:调用LocalDate类的.until方法,返回 总的相差的年数、月数与天数
// 指定转换格式 DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd"); LocalDate startDate = LocalDate.parse("2019-03-01",fmt); LocalDate endDate = LocalDate.parse("2020-04-02",fmt); System.out.println("总相差的天数:" + startDate.until(endDate, ChronoUnit.DAYS)); System.out.println("总相差的月数:" + startDate.until(endDate, ChronoUnit.MONTHS)); System.out.println("总相差的年数:" + startDate.until(endDate, ChronoUnit.YEARS));
输出:
总相差的天数:398 总相差的月数:13 总相差的年数:1
方法三:调用LocalDate类的toEpochDay方法,返回距离1970年1月1日的long值
此方法只能计算两个LocalDate日期间的天数,不能计算月份、年数
LocalDate start = LocalDate.of(2020,2,28); LocalDate end = LocalDate.of(2021,12,3); System.out.println("两个时间之间的相差的天数: "+(end.toEpochDay()-start.toEpochDay())); //644