高级JAVA开发必备技能:java8 新日期时间API((二)JSR-310:常用的日期时间API)(JAVA 小虚竹

+ [TickClock](#TickClock_204)

常用的日期时间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 是抽象类,内部提供了四个内部类,这是它的内部实现类

image-2021081496702

  • 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);

image-20210814195855581

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

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

		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());

image-202108149044323

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());


image-202108141995813

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());

image-20210814944060

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());

image-20210814904947

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

Clock.systemDefaultZone()

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

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

image-2021081495878

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

Clock.systemUTC()

用的是UTC时区ZoneOffset.UTC

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

image-2021081495878

最终调用的也是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) ;

image-202108149595

实战:

		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);

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

image-20210814909314

image-2021081495696

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()); // 毫秒

image-20210720905353

Instant是没有时区的,但是Instant加上时区后,可以转化为ZonedDateTime
		Instant ins = Instant.now();
		ZonedDateTime zdt = ins.atZone(ZoneId.systemDefault());
		System.out.println(zdt);

image-202107205211996

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);

image-202107234326190

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);

image-2021081496781

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

image-2021081497325

获取指定日期的年月日
		
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());

image-2021081498430

修改年月日
		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));

image-20210814935404

比较日期
		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)));

image-202108149597

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);

image-2021081499979

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);

image-2021081492237

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格式打印

image-20210714857780

由运行结果可行,本地日期时间通过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);

image-20210714803165

日期时间的加减法及修改
		LocalDateTime currentTime = LocalDateTime.now(); // 当前日期和时间
		System.out.println("------------------时间的加减法及修改-----------------------");
		//3.LocalDateTime的加减法包含了LocalDate和LocalTime的所有加减,上面说过,这里就只做简单介绍
		System.out.println("3.当前时间:" + currentTime);
		System.out.println("3.当前时间加5年:" + currentTime.plusYears(5));
		System.out.println("3.当前时间加2个月:" + currentTime.plusMonths(2));
		System.out.println("3.当前时间减2天:" + currentTime.minusDays(2));
		System.out.println("3.当前时间减5个小时:" + currentTime.minusHours(5));
		System.out.println("3.当前时间加5分钟:" + currentTime.plusMinutes(5));
		System.out.println("3.当前时间加20秒:" + currentTime.plusSeconds(20));
		//还可以灵活运用比如:向后加一年,向前减一天,向后加2个小时,向前减5分钟,可以进行连写
		System.out.println("3.同时修改(向后加一年,向前减一天,向后加2个小时,向前减5分钟):" + currentTime.plusYears(1).minusDays(1).plusHours(2).minusMinutes(5));
		System.out.println("3.修改年为2025年:" + currentTime.withYear(2025));
		System.out.println("3.修改月为12月:" + currentTime.withMonth(12));
		System.out.println("3.修改日为27日:" + currentTime.withDayOfMonth(27));
		System.out.println("3.修改小时为12:" + currentTime.withHour(12));
		System.out.println("3.修改分钟为12:" + currentTime.withMinute(12));
		System.out.println("3.修改秒为12:" + currentTime.withSecond(12));

image-20210714941902

LocalDateTime和Date相互转化
Date转LocalDateTime
		System.out.println("------------------方法一:分步写-----------------------");
		//实例化一个时间对象
		Date date = new Date();
		//返回表示时间轴上同一点的瞬间作为日期对象
		Instant instant = date.toInstant();
		//获取系统默认时区
		ZoneId zoneId = ZoneId.systemDefault();
		//根据时区获取带时区的日期和时间
		ZonedDateTime zonedDateTime = instant.atZone(zoneId);
		//转化为LocalDateTime
		LocalDateTime localDateTime = zonedDateTime.toLocalDateTime();
		System.out.println("方法一:原Date = " + date);
		System.out.println("方法一:转化后的LocalDateTime = " + localDateTime);

		System.out.println("------------------方法二:一步到位(推荐使用)-----------------------");
		//实例化一个时间对象
		Date todayDate = new Date();
		//Instant.ofEpochMilli(long l)使用1970-01-01T00:00:00Z的纪元中的毫秒来获取Instant的实例
		LocalDateTime ldt = Instant.ofEpochMilli(todayDate.getTime()).atZone(ZoneId.systemDefault()).toLocalDateTime();
		System.out.println("方法二:原Date = " + todayDate);
		System.out.println("方法二:转化后的LocalDateTime = " + ldt);

image-20210714210839339

LocalDateTime转Date
		System.out.println("------------------方法一:分步写-----------------------");
		//获取LocalDateTime对象,当前时间
		LocalDateTime localDateTime = LocalDateTime.now();
		//获取系统默认时区
		ZoneId zoneId = ZoneId.systemDefault();
		//根据时区获取带时区的日期和时间
		ZonedDateTime zonedDateTime = localDateTime.atZone(zoneId);
		//返回表示时间轴上同一点的瞬间作为日期对象
		Instant instant = zonedDateTime.toInstant();
		//转化为Date
		Date date = Date.from(instant);
		System.out.println("方法一:原LocalDateTime = " + localDateTime);
		System.out.println("方法一:转化后的Date = " + date);

		System.out.println("------------------方法二:一步到位(推荐使用)-----------------------");
		//实例化一个LocalDateTime对象
		LocalDateTime now = LocalDateTime.now();
		//转化为date
		Date dateResult = Date.from(now.atZone(ZoneId.systemDefault()).toInstant());
		System.out.println("方法二:原LocalDateTime = " + now);
		System.out.println("方法二:转化后的Date = " + dateResult);

image-20210714211035080

LocalTime

LocalTime类说明

LocalTime:本地时间,只有表示时分秒

LocalTime常用的用法

获取当前时间
		LocalTime localTime1 = LocalTime.now();
		LocalTime localTime2 = LocalTime.now(ZoneId.of("Asia/Shanghai"));
		LocalTime localTime3 = LocalTime.now(Clock.systemDefaultZone());

		System.out.println("now :"+localTime1);
		System.out.println("now by zone :"+localTime2);
		System.out.println("now by Clock:"+localTime3);

image-2021081498171

获取LocalTime对象
		LocalTime localTime1 = LocalTime.of(23, 26, 30);
		LocalTime localTime2 = LocalTime.of(23, 26);
		System.out.println(localTime1);
		System.out.println(localTime2);

image-2021081494673

获取指定日期的时分秒
		LocalTime localTime1 = LocalTime.of(23, 26, 30);
		//当前时间的时:23
		System.out.println(localTime1.getHour());
		//当前时间的分:26
		System.out.println(localTime1.getMinute());
		//当前时间的秒:30
		System.out.println(localTime1.getSecond());

image-2021081492055

修改时分秒
		LocalTime localTime1 = LocalTime.of(23, 26, 30);
		//修改时间的时:00:26:30
		System.out.println(localTime1.withHour(0));
		//修改时间的分:23:30:30
		System.out.println(localTime1.withMinute(30));
		//修改时间的秒:23:26:59
		System.out.println(localTime1.withSecond(59));

image-202108149774

比较时间
		LocalTime localTime1 = LocalTime.of(23, 26, 30);
		LocalTime localTime2 = LocalTime.of(23, 26, 32);
		// 两个时间进行比较 大返回1,小就返回-1,一样就返回0:-1
		System.out.println(localTime1.compareTo(localTime2));

		// 比较指定时间是否比参数时间早(true为早):true
		System.out.println(localTime1.isBefore(localTime2));
		// 比较指定时间是否比参数时间晚(true为晚):false
		System.out.println(localTime1.isAfter(localTime2));


### 最后

Python崛起并且风靡,因为优点多、应用领域广、被大牛们认可。学习 Python 门槛很低,但它的晋级路线很多,通过它你能进入机器学习、数据挖掘、大数据,CS等更加高级的领域。Python可以做网络应用,可以做科学计算,数据分析,可以做网络爬虫,可以做机器学习、自然语言处理、可以写游戏、可以做桌面应用…Python可以做的很多,你需要学好基础,再选择明确的方向。这里给大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!

#### 👉Python所有方向的学习路线👈

Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。

![](https://img-blog.csdnimg.cn/img_convert/604bae65027d4d67fb62410deb210454.png)

#### 👉Python必备开发工具👈

工欲善其事必先利其器。学习Python常用的开发软件都在这里了,给大家节省了很多时间。

![](https://img-blog.csdnimg.cn/img_convert/fa276175617e0048f79437bd30465479.png)



#### 👉Python全套学习视频👈

我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了。

![](https://img-blog.csdnimg.cn/img_convert/16ac689cb023166b2ffa9c677ac40fc0.png)



#### 👉实战案例👈



学python就与学数学一样,是不能只看书不做题的,直接看步骤和答案会让人误以为自己全都掌握了,但是碰到生题的时候还是会一筹莫展。



因此在学习python的过程中一定要记得多动手写代码,教程只需要看一两遍即可。

![](https://img-blog.csdnimg.cn/img_convert/0d8c31c50236a205928a1d8ae8a0b883.png)



#### 👉大厂面试真题👈

我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

![](https://img-blog.csdnimg.cn/img_convert/99461e47e58e503d2bc1dc6f4668534a.png)

**[需要这份系统化学习资料的朋友,可以戳这里无偿获取](https://bbs.csdn.net/topics/618317507)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
  • 23
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值