「JDK8」Duration、Period计算日期、时间间隔

前言

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

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 getSeconds() 将时间转换为以秒为单位的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.getSeconds());
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

计算两个时间间隔

方法一:

通过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分钟

 方法三:

通过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秒

计算两个时间戳的间隔

项目中经常会有时间戳的值,下面的示例一起看一下如何比较时间戳。

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

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

计算两个日期相差的具体天数

方法一:

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类的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

 

posted @ 2022-06-16 13:14  残城碎梦  阅读(1524)  评论(0编辑  收藏  举报