高级java开发必须掌握技能java8新日期时间api(jsr-310:常用的日期时间api),4万字详解(全程干货,建议收藏)(代码片段)

小虚竹 小虚竹     2022-12-24     255

关键词:

技术活,该赏
点赞,收藏再看,养成习惯

大家好,我是小虚竹。之前有粉丝私聊我,问能不能把JAVA8 新的日期时间API(JSR-310)知识点梳理出来。答案是肯定的,谁让我宠粉呢。由于内容偏多(超十万字了),会拆成多篇来写。

闲话就聊到这,请看下面的正文。

文章目录

常用的日期时间API简介

介绍下java8API比较常用的日期时间API,按java.time 包的类顺序:

  • Clock:时钟
  • Instant:瞬间时间。
  • LocalDate:本地日期。只有表示年月日
  • LocalDateTime:本地日期时间,LocalDate+LocalTime
  • LocalTime:本地时间,只有表示时分秒
  • OffsetDateTime:有时间偏移量的日期时间(不包含基于ZoneRegion的时间偏移量)
  • OffsetTime:有时间偏移量的时间
  • ZonedDateTime:有时间偏移量的日期时间(包含基于ZoneRegion的时间偏移量)

博主把这些类都点开看了,都是属于不可变类。而且官方也说了,java.time包 下的类都是线程安全的。

Clock

Clock类说明

public abstract class Clock 
...

Clock 是抽象类,内部提供了四个内部类,这是它的内部实现类

  • FixedClock :始终返回相同瞬间的时钟,通常使用于测试。
  • OffsetClock :偏移时钟,时间偏移量的单位是Duration。
  • SystemClock :系统默认本地时钟。
  • TickClock :偏移时钟,时间偏移量的单位是纳秒。

Clock 提供了下面这几个常用的方法(这几个方法在实现类里都有对应的实现):

// 获取时钟的当前Instant对象。
public abstract Instant instant()

// 获取时钟的当前毫秒数值
public long millis()

// 获取用于创建时钟的时区。
public abstract ZoneId	getZone()

// 返回具有指定时区的当前时钟的新实例
public abstract Clock withZone(ZoneId zone)

FixedClock

Clock.fixed

public static Clock fixed(Instant fixedInstant, ZoneId zone)

需要传递instantzone,并将返回具有固定瞬间的时钟。

		Instant instant = Instant.now();
		Clock fixedClock = Clock.fixed(instant, ZoneId.of("Asia/Shanghai"));
		Clock fixedClock1 = Clock.fixed(instant, ZoneId.of("GMT"));
		System.out.println("中国时区的Clock:"+fixedClock);
		System.out.println("GMT时区的Clock:"+fixedClock1);

由运行结果可知,返回的结果是有带对应时区的。

验证获取的时钟会不会改变:

		Clock clock = Clock.systemDefaultZone();
		Clock fixedClock = Clock.fixed(clock.instant(), ZoneId.of("Asia/Shanghai"));
		System.out.println(fixedClock.instant());
		try 
			Thread.sleep(1000);
		 catch (InterruptedException e) 
			e.printStackTrace();
		
		System.out.println(fixedClock.instant());

Clock.fixed 创建一个固定的时钟,clock 对象将始终提供与指定相同的时刻。。如图所示,强制睡眠1秒,但是时刻没变。

Clock.fixed 跟 Offset 方法更配

由上面可知Clock.fixed 得到一个固定的时钟,那要添加时间或者减去时间就要用到Offset 方法

示例代码如下

		Clock clock = Clock.systemDefaultZone();
		Clock fixedClock = Clock.fixed(clock.instant(), ZoneId.of("Asia/Shanghai"));
		System.out.println(fixedClock.instant());
		Clock clockAdd = Clock.offset(clock, Duration.ofMinutes(20));
		Clock clockSub = Clock.offset(clock, Duration.ofMinutes(-10));
		System.out.println("原先的: " + clock.instant());
		System.out.println("加了20分钟: " + clockAdd.instant());
		System.out.println("减了10分钟: " + clockSub.instant());

OffsetClock

OffsetClock 是偏移时钟,时间偏移量的单位是Duration。

//Clock
     public static Clock offset(Clock baseClock, Duration offsetDuration) 
        Objects.requireNonNull(baseClock, "baseClock");
        Objects.requireNonNull(offsetDuration, "offsetDuration");
        if (offsetDuration.equals(Duration.ZERO)) 
            return baseClock;
        
        return new OffsetClock(baseClock, offsetDuration);
    

由源码可知,使用Clock.offset方法 返回的是OffsetClock实例对象

		Clock clock = Clock.systemDefaultZone();
		Clock fixedClock = Clock.fixed(clock.instant(), ZoneId.of("Asia/Shanghai"));
		System.out.println(fixedClock.instant());
		Clock clockAdd = Clock.offset(clock, Duration.ofMinutes(20));
		System.out.println("原先的: " + clock.instant());
		System.out.println("加了20分钟: " + clockAdd.instant());

SystemClock

SystemClock 是系统默认的本地时钟。

		Clock clock = Clock.systemDefaultZone();		System.out.println(clock.millis());		Clock utc = Clock.systemUTC();		System.out.println(utc.millis());		System.out.println(System.currentTimeMillis());

居然完全一样。这就要看下源码了

Clock.systemDefaultZone()

用的是系统默认的时区ZoneId.systemDefault()

    public static Clock systemDefaultZone() 
        return new SystemClock(ZoneId.systemDefault());
    

最终调用的也是System.currentTimeMillis()

Clock.systemUTC()

用的是UTC时区ZoneOffset.UTC

    public static Clock systemUTC()         return new SystemClock(ZoneOffset.UTC);    

最终调用的也是System.currentTimeMillis()

结论

Clock.systemDefaultZone() 和Clock.systemUTC()获取的millis()时间戳是一样的,就是对应时区的差别。

TickClock

TickClock 是偏移时钟,时间偏移量的最小单位是纳秒。

如图所示,Clock主要提供下面三个方法

//构造的时钟的计时单位是自定义的偏移量单位public static Clock tick(Clock baseClock, Duration tickDuration); //构造的时钟的计时单位是分 public static Clock tickMinutes(ZoneId zone);//构造的时钟的计时单位是秒public static Clock tickSeconds(ZoneId zone) ;

实战:

		Clock tickClock = Clock.tick(Clock.systemDefaultZone(),Duration.ofHours(1L));		Clock tickMinutes = Clock.tickMinutes(ZoneId.of("Asia/Shanghai"));		Clock tickSeconds = Clock.tickSeconds(ZoneId.of("Asia/Shanghai"));		LocalDateTime tickClockLocalDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(tickClock.millis()),ZoneId.of("Asia/Shanghai"));		LocalDateTime tickMinutesLocalDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(tickMinutes.millis()),ZoneId.of("Asia/Shanghai"));		LocalDateTime tickSecondsLocalDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(tickSeconds.millis()),ZoneId.of("Asia/Shanghai"));		System.out.println("tickClock  :"+tickClock.millis() +" 转为date时间:"+tickClockLocalDateTime);		System.out.println("tickMinutes:"+tickMinutes.millis() +" 转为date时间:"+tickMinutesLocalDateTime);		System.out.println("tickSeconds:"+tickSeconds.millis() +" 转为date时间:"+tickSecondsLocalDateTime);

偏移量的单位支持:天,时,分,秒,豪秒,纳秒

Instant

Instant类说明

public final class Instant        implements Temporal, TemporalAdjuster, Comparable<Instant>, Serializable         ...        

Instant表示瞬间时间。也是不可变类且是线程安全的。其实Java.time 这个包是线程安全的。

Instant是java 8新增的特性,里面有两个核心的字段

	...		private final long seconds;        private final int nanos;	...

一个是单位为秒的时间戳,另一个是单位为纳秒的时间戳。

是不是跟**System.currentTimeMillis()**返回的long时间戳很像,System.currentTimeMillis()返回的是毫秒级,Instant多了更精确的纳秒级时间戳。

Instant常用的用法

 		Instant now = Instant.now();
		System.out.println("now:"+now);
		System.out.println(now.getEpochSecond()); // 秒
		System.out.println(now.toEpochMilli()); // 毫秒

Instant是没有时区的,但是Instant加上时区后,可以转化为ZonedDateTime

		Instant ins = Instant.now();
		ZonedDateTime zdt = ins.atZone(ZoneId.systemDefault());
		System.out.println(zdt);

long型时间戳转Instant

要注意long型时间戳的时间单位选择Instant对应的方法转化

//1626796436 为秒级时间戳Instant ins = Instant.ofEpochSecond(1626796436);ZonedDateTime zdt = ins.atZone(ZoneId.systemDefault());System.out.println("秒级时间戳转化:"+zdt);//1626796436111l 为秒级时间戳Instant ins1 = Instant.ofEpochMilli(1626796436111l);ZonedDateTime zdt1 = ins1.atZone(ZoneId.systemDefault());System.out.println("毫秒级时间戳转化:"+zdt1);

Instant的坑

Instant.now()获取的时间与北京时间相差8个时区,这是一个细节,要避坑。

看源码,用的是UTC时间。

public static Instant now()         return Clock.systemUTC().instant();    

解决方案:

Instant now = Instant.now().plusMillis(TimeUnit.HOURS.toMillis(8));System.out.println("now:"+now);

LocalDate

LocalDate类说明

LocalDate表示本地日期。只有表示年月日。相当于:yyyy-MM-dd。

LocalDate常用的用法

获取当前日期

		LocalDate localDate1 = LocalDate.now();		LocalDate localDate2 = LocalDate.now(ZoneId.of("Asia/Shanghai"));		LocalDate localDate3 = LocalDate.now(Clock.systemUTC());		System.out.println("now         :"+localDate1);		System.out.println("now by zone :"+localDate2);		System.out.println("now by Clock:"+localDate3);

获取localDate对象

		LocalDate localDate1 = LocalDate.of(2021, 8, 14);		LocalDate localDate2 = LocalDate.parse("2021-08-14");		System.out.println(localDate1);		System.out.println(localDate2);

获取指定日期的年月日

		LocalDate localDate1 = LocalDate.of(2021, 8, 14);		// 当前日期年份:2021		System.out.println(localDate1.getYear());		// 当前日期月份对象:AUGUST		System.out.println(localDate1.getMonth());		// 当前日期月份:8		System.out.println(localDate1.getMonthValue());		// 该日期是当前周的第几天:6		System.out.println(localDate1.getDayOfWeek().getValue());		// 该日期是当前月的第几天:14		System.out.println(localDate1.getDayOfMonth());		// 该日期是当前年的第几天:226		System.out.println(localDate1.getDayOfYear());

修改年月日

		LocalDate localDate1 = LocalDate.of(2021, 8, 14);		// 修改该日期的年份:2022-08-14		System.out.println(localDate1.withYear(2022));		// 修改该日期的月份:2021-12-14		System.out.println(localDate1.withMonth(12));		// 修改该日期在当月的天数:2021-08-01		System.out.println(localDate1.withDayOfMonth(1));

比较日期

		LocalDate localDate1 = LocalDate.of(2021, 8, 14);		// 比较指定日期和参数日期,返回正数,那么指定日期时间较晚(数字较大):13		int i = localDate1.compareTo(LocalDate.of(2021, 8, 1));		System.out.println(i);		// 比较指定日期是否比参数日期早(true为早):true		System.out.println(localDate1.isBefore(LocalDate.of(2021,8,31)));		// 比较指定日期是否比参数日期晚(true为晚):false		System.out.println(localDate1.isAfter(LocalDate.of(2021,8,31)));		// 比较两个日期是否相等:true		System.out.println(localDate1.isEqual(LocalDate.of(2021, 8, 14)));

LocalDate 和String相互转化、Date和LocalDate相互转化

LocalDate 和String相互转化

		LocalDate localDate1 = LocalDate.of(2021, 8, 14);		// LocalDate 转 String		DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");		String dateString = localDate1.format(dateTimeFormatter);		System.out.println("LocalDate 转 String:"+dateString);		// String 转 LocalDate		String str = "2021-08-14";		DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd");		LocalDate date = LocalDate.parse(str, fmt);		System.out.println("String 转 LocalDate:"+date);

Date和LocalDate相互转化

	// Date 转 LocalDate
		Date now = new Date();
		// 先将Date转换为ZonedDateTime
		Instant instant = now.toInstant();
		ZonedDateTime zonedDateTime = instant.atZone(ZoneId.of("Asia/Shanghai"));
		LocalDate localDate = zonedDateTime.toLocalDate();
		// Sat Aug 14 23:16:28 CST 2021
		System.out.println(now);
		// 2021-08-14
		System.out.println(localDate);

		// LocalDate 转 Date
		LocalDate now1 = LocalDate.now();
		ZonedDateTime dateTime = now1.atStartOfDay(ZoneId.of("Asia/Shanghai"));
		Date date1 = Date.from(dateTime.toInstant());
		System.out.println(date1);

LocalDateTime

LocalDateTime类说明

表示当前日期时间,相当于:yyyy-MM-ddTHH:mm:ss

LocalDateTime常用的用法

获取当前日期和时间

		LocalDate d = LocalDate.now(); // 当前日期
		LocalTime t = LocalTime.now(); // 当前时间
		LocalDateTime dt = LocalDateTime.now(); // 当前日期和时间
		System.out.println(d); // 严格按照ISO 8601格式打印
		System.out.println(t); // 严格按照ISO 8601格式打印
		System.out.println(dt); // 严格按照ISO 8601格式打印

由运行结果可行,本地日期时间通过now()获取到的总是以当前默认时区返回的

获取指定日期和时间

		LocalDate d2 = LocalDate.of(2021, 07, 14); // 2021-07-14, 注意07=07月		LocalTime t2 = LocalTime.of(13, 14, 20); // 13:14:20		LocalDateTime dt2 = LocalDateTime.of(2021, 07, 14, 13, 14, 20);		LocalDateTime dt3 = LocalDateTime.of(d2, t2);		System.out.println("指定日期时间:"+dt2);		System.out.println("指定日期时间:"+dt3);

日期时间的加减法及修改

		LocalDateTim

高级java开发必备技能:java8新日期时间api(jsr-310:常用的日期时间api)(java小虚竹)(代码片段)

技术活,该赏点赞,收藏再看,养成习惯大家好,我是小虚竹。之前有粉丝私聊我,问能不能把JAVA8新的日期时间API(JSR-310)知识点梳理出来。答案是肯定的,谁让我宠粉呢。由于内容偏多(超... 查看详情

❤️高级java开发必备技能❤️java8新日期时间api(jsr-310:实战+源码分析),5万字详解(java小虚竹,建议收藏)(代码片段)

❤️作者简介:Java领域优质创作者🏆,CSDN博客专家认证🏆❤️技术活,该赏❤️点赞👍收藏⭐再看,养成习惯大家好,我是小虚竹。之前有粉丝私聊我,问能不能把JAVA8新的日期时间API(... 查看详情

❤️高级java开发必备技能❤️java8新日期时间api(jsr-310:常用计算工具),2万字详解(java小虚竹,建议收藏)(代码片段)

❤️作者简介:Java领域优质创作者🏆,博客专家认证🏆❤️技术活,该赏❤️点赞👍收藏⭐再看,养成习惯大家好,我是小虚竹。之前有粉丝私聊我,问能不能把JAVA8新的日期时间API(JSR-... 查看详情

❤️高级java开发必备技能❤️java8新日期时间api(jsr-310:格式化和解析),2万字详解(java小虚竹,建议收藏)(代码片段)

技术活,该赏点赞,收藏再看,养成习惯大家好,我是小虚竹。之前有粉丝私聊我,问能不能把JAVA8新的日期时间API(JSR-310)知识点梳理出来。答案是肯定的,谁让我宠粉呢。由于内容偏多(超... 查看详情

高级java开发必备技能:java8新日期时间api(jsr-310:常用计算工具)(java小虚竹)(代码片段)

❤️作者简介:Java领域优质创作者🏆,博客专家认证🏆❤️技术活,该赏❤️点赞👍收藏⭐再看,养成习惯大家好,我是小虚竹。之前有粉丝私聊我,问能不能把JAVA8新的日期时间API(JSR-... 查看详情

高级java开发必备技能:java8新日期时间api(jsr-310:实战+源码分析)(java小虚竹)(代码片段)

❤️作者简介:Java领域优质创作者🏆,CSDN博客专家认证🏆❤️技术活,该赏❤️点赞👍收藏⭐再看,养成习惯大家好,我是小虚竹。之前有粉丝私聊我,问能不能把JAVA8新的日期时间API(... 查看详情

高级java开发必备技能:java8新日期时间api(jsr-310:格式化和解析)(java小虚竹)(代码片段)

技术活,该赏点赞,收藏再看,养成习惯大家好,我是小虚竹。之前有粉丝私聊我,问能不能把JAVA8新的日期时间API(JSR-310)知识点梳理出来。答案是肯定的,谁让我宠粉呢。由于内容偏多(超... 查看详情

高级java开发必备技能:java8新日期时间api(jsr-310:zoneid时区和偏移量)(java小虚竹)(代码片段)

技术活,该赏点赞再看,养成习惯大家好,我是小虚竹。之前有粉丝私聊我,问能不能把JAVA8新的日期时间API(JSR-310)知识点梳理出来。答案是肯定的,谁让我宠粉呢。由于内容偏多(超十万字了&#... 查看详情

高级java工程师必须掌握的技能

650)this.width=650;"src="https://i1.go2yd.com/image.php?url=0GqtKQEw3W"style="vertical-align:middle;padding:0px;border:none;margin:0pxauto20px;background:rgb(230,230,230)url("http://static.yidian 查看详情

学习java必须掌握的高级技能总结(代码片段)

 注:我也是小白一名,这些内容我都是我在百度去学习之后复制到这里形成博客。希望对大家有帮助。 1.Java基础技术体系java体系基础理论编程语言:系统级:C,C++,go,erlang...应用级:C#,Java,Python,Perl,Ruby,php虚拟机:jvm(java虚拟机)... 查看详情

java8新特性不了解optional类,简历上别说你懂java8!!

...分写着:熟练掌握Java8的各种新特性,能够迅速使用Java8开发高并发应用!这不,又一名读者因为写了熟练掌握Java8的新特性而被面试官虐的体无完肤!我不是说不能写,可以这样写!但是,咱在写熟练掌握Java8新特性的时候,应... 查看详情

java8新特性关于并行流与串行流,你必须掌握这些!!

写在前面提到Java8,我们不得不说的就是Lambda表达式和StreamAPI。而在Java8中,对于并行流和串行流同样做了大量的优化。对于并行流和串行流的知识,也是在面试过程中,经常被问到的知识点。当然,我们不能只是为了应付面试... 查看详情

在java8中如何处理日期和时间

...案是在实际项目中使用它。项目中有很多真正的需求驱使开发者去发掘并学习新库。简单得说就是任务驱动学习探索。这对Java8新日期时间API也不例外。我创建了20个基于任务的实例来学习Java8的新特性。从最简单创建当天的日期... 查看详情

jdk都出到16了8还没掌握吗?挽周带你玩转java8新特性(建议收藏)(代码片段)

Java8新特性Java8(又称为jdk1.8)是Java语言开发的一个主要版本。Oracle公司于2014年3月18日发布Java8,它支持函数式编程,新的JavaScript引擎,新的日期API,新的StreamAPI等。在本文中我们将围绕以下五点学习(常用的)新特性... 查看详情

别再用date了,死磕java8新特性,18种日期处理方式!(代码片段)

...击上方关注“终端研发部”设为“星标”,和你一起掌握更多数据库知识伴随 lambda表达式、 streams 以及一系列小优化,Java8推出了全新的日期时间API。Java处理日期、日历和时间的不足之处:将java.util.Date设定为可变... 查看详情

java8新特性之日期和时间

在Java8以前,日期和时间处理一直被广大java程序员抱怨太难用,java.util和java.sql中,都包含Date类,如果要进行时间格式化,还需要java.text.DateFormat类处理。同时java.util.Date中既包含了日期,又包含了时间,所以java8新的日期和时间... 查看详情

java8新特性-----新时间与日期api(代码片段)

新时间与日期API新的时间和日期APIInstant:时间戳Duration计算时间间隔,Period计算日期间隔时间校正器时间和日期格式化---DateTimeFormatter新的时间和日期API//只获取当前系统的日期LocalDatenow=LocalDate.now();System.out.println("当前... 查看详情

java8新特性学习六(新时间日期api)

在java8以前,做有关时间日期的操作时使用java.util.Date,做日期、月份、天数相加减操作时使用java.util.Calendar,对时间日期进行格式化操作时,使用SimpleDateFormat或DateFormat下的其他子类;但是这些时间日期操作对象,都是可变的、... 查看详情