Java8日期时间API(一) 日期时间的获取、修改和比较

1.旧版本存在的问题

相信有开发经验的朋友都清楚Java旧版的时间方面的API设计不合理,没有时区支持、日期时间的计算和时间格式的转化都很麻烦。且时间格式转换在多线程环境下容易出现线程安全问题

多线程环境下SimpleDateFormat线程安全问题

因此,一般小姜在平时的开发中使用hutool的工具类进行时间的计算,在ThreadLocal中加入SimpleDateFormat供该线程共享

2.新版本的改进

JDK8中新增加了一套全新的七日时间API,这套API的设计合理,并且是线程安全的,主要的类有

  • LOcalDate: 表示日期,例如 2000-01-01
  • LocalTime: 表示时间,例如 12:00:00.200
  • LocalDateTime: 标识日期时间,例如 2000-01-01 12:00:00.200
  • DateTimeFormatter: 日期时间格式化类
  • Instant: 时间戳,表示某一个瞬间
  • Duration: 用于计算两个时间(LocalTime,时分秒)之间的差值
  • Perlod: 用于计算两个日期(LOcalDate,年月日)之间的差值
  • ZonedDateTime: 支持时区的日期时间

除此之外,默认情况下我们使用的是公元纪年也就是公历,JDK8还提供了其他历法:

  • ThaiBuddhistDate 泰国佛教历
  • MinguoDate 中华民国历
  • JapaneseDate 日本历
  • HijrahDate 伊斯兰历

了解这些之后,我们来看一下JDK8相关的时间操作

3.JDK8时间相关操作

3.1创建时间

// 旧版本创建日期
Date oldDate = new Date(2000, 1, 1);
System.out.println(oldDate);

// 新版本创建日期
LocalDate newDate = LocalDate.of(2000, 1, 1);
System.out.println(newDate);
执行结果:

可见,新版本创建的日期是完全正确的,而旧版本创建的却是3900年2月1日,这是因为旧版本的Date在传入参数的时候需要传递的年份参数是指定参数距离1900年的差值。比如2000年距离1900年差了100年那么Date就应该传入100,而月份传入参数的时候取0~11,0表示1月份;1标识2月份,以此类推11表示的就是12月份。

此外,严格来说Date创建的是2000-01-01 00:00:00这个时间点而不是单纯的表示2000-01-01这一天。新版本表示的更为准确,同时帮我们做了格式化。

3.2获取当前日期

// 获取当前日期
LocalDate now = LocalDate.now();

System.out.println("当前日期:" + now);
System.out.println("年: " + now.getYear());
System.out.println("月: " + now.getMonth().getValue());
System.out.println("日: " + now.getDayOfMonth());
System.out.println("星期: " + now.getDayOfWeek().getValue());
执行结果:


LocalDate对象获得的月份和星期几时枚举值,需要getValue()才能获取到响应的int值,以上结果,今天确实是2021年6月21日星期一

3.3时间操作

// 创建指定的时间
LocalTime time = LocalTime.of(12, 26, 30, 100);
System.out.println("指定时间:" + time);

LocalTime nowTime = LocalTime.now();
System.out.println("当前时间:" + nowTime);
System.out.println("时:" + nowTime.getHour());
System.out.println("分:" + nowTime.getMinute());
System.out.println("秒:" + nowTime.getSecond());
System.out.println("纳秒:" + nowTime.getNano());
执行结果

3.4日期时间操作

// 创建指定日期时间 2000-01-01 12:26:38
LocalDateTime dateTime = LocalDateTime.of(2000,1,1,12,26,38);
System.out.println("指定的日期时间:" + dateTime);

// 获取当前日期时间
LocalDateTime nowDateTime = LocalDateTime.now();
System.out.println("当前的日期时间:" + nowDateTime);
System.out.println("年:" + nowDateTime.getYear());
System.out.println("月:" + nowDateTime.getMonth().getValue());
System.out.println("日:" + nowDateTime.getDayOfMonth());
System.out.println("时:" + nowDateTime.getHour());
System.out.println("分:" + nowDateTime.getMinute());
System.out.println("秒:" + nowDateTime.getSecond());
System.out.println("纳秒:" + nowDateTime.getNano());
System.out.println("星期:" + nowDateTime.getDayOfWeek().getValue());

3.5日期时间的修改

JDK8中修改日期时间的方法是dateTime.withXXX看到名字就能知道是修改什么,比如说:

  • withYear 修改年份
  • withMonth 修改月份
  • withDayOfMonth 修改在某月的第几天也就是几号
// 创建指定日期时间 2000-01-01 12:26:38
LocalDateTime dateTime = LocalDateTime.of(2000,1,1,12,26,38);
System.out.println("指定的日期时间:" + dateTime);

// 修改年份为2008年
LocalDateTime dateTime20008 = dateTime.withYear(2008);
System.out.println(dateTime20008);
System.out.println(dateTime);
执行结果


以上结果可见,修改日期时间对象时;并不会修改原来的对象。而是会生成一个新的对象,复制原来的对象,然后修改制定的参数。如上面的代码中我将dateTime对象中的年份改成2008年但是dateTime对象中的年份并没有发生变化,而withYear返回的对象dateTime20008只是修改了制定的年份,其他并没法发生变化,因此若想一次修改多个参数可以这样做:

// 创建指定日期时间 2000-01-01 12:26:38
LocalDateTime dateTime = LocalDateTime.of(2000,1,1,12,26,38);
System.out.println("指定的日期时间:" + dateTime);

// 修改年份为2008-08-08 12:26:38
LocalDateTime dateTime20008 = dateTime.withYear(2008).withMonth(8).withDayOfMonth(8);
System.out.println(dateTime20008);
System.out.println(dateTime);
执行结果


可见,原来的dateTime也并没有变化dateTime.withXXX方法返回的是一个新的对象

3.6时间的位移计算

在项目中有时我们需要计算当前时间n小时之前或n小时之后,此类的时间位移计算,在JDK8中提供了plusXXX(加)和minusXXX(减)方法用于进行位移计算。

plusXXX用于进行日期时间的加法运算,常用的有:

  • plusHours 计算n个小时之后的日期时间
  • plusYears 计算n年之后的日期时间
  • plusMonths 计算n个月之后的日期时间
  • plusDays 计算n天之后的日期时间
  • plusMinutes 计算n分钟之后的日期时间
  • plusWeeks 计算n周之后的日期时间

minusXXX用于进行日期时间的减法运算,常用的有:

  • minusHours 计算n个小时之前的日期时间
  • minusYears 计算n年之前的日期时间
  • minusMonths 计算n个月之前的日期时间
  • minusDays 计算n天之前的日期时间
  • minusMinutes 计算n分钟之前的日期时间
  • minusWeeks 计算n周之前的日期时间
// 获取当前日期时间
LocalDateTime nowDateTime = LocalDateTime.now();

System.out.println("当前日期时间:" + nowDateTime);

// 进行时间的位移计算
System.out.println("一小时后:" + nowDateTime.plusHours(1));
System.out.println("2年后:" + nowDateTime.plusYears(2));
System.out.println("3个月后:" + nowDateTime.plusMonths(3));
System.out.println();
System.out.println("一天前:" + nowDateTime.minusDays(1));
System.out.println("10分钟前:" + nowDateTime.minusMinutes(10));
System.out.println("2周前:" + nowDateTime.minusWeeks(2));
执行结果

3.7 时间的比较

  • date1.isAfter(date2) date1是否在date2之后
  • date1.isBefore(date2) date1是否在date2之前
  • date1.isLeapYear() date1所处年份是否是闰年
// 获取当前日期时间
LocalDate nowDate = LocalDate.now();
LocalDate date = LocalDate.of(2020, 2, 17);

System.out.println( "当前时间是否在 2020-02-17之后: " + nowDate.isAfter(date));
System.out.println("当前时间是否在 2020-02-17之前: " + nowDate.isBefore(date));
System.out.println("当前年份是否是闰年: " + nowDate.isLeapYear());
System.out.println("2020-02-17是否是闰年: " + date.isLeapYear());
执行结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值