高级JAVA开发必备技能:java8 新日期时间API(JSR-310:实战+源码分析)(JAVA 小虚竹)

Posted 小虚竹

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高级JAVA开发必备技能:java8 新日期时间API(JSR-310:实战+源码分析)(JAVA 小虚竹)相关的知识,希望对你有一定的参考价值。

❤️作者简介:Java领域优质创作者🏆,CSDN博客专家认证🏆
❤️技术活,该赏
❤️点赞 👍 收藏 ⭐再看,养成习惯

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

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

使用场景

对JDK8+中的日期时间工具类封装

项目引用

此博文的依据:hutool-5.6.5版本源码

        <dependency>
			<groupId>cn.hutool</groupId>
			<artifactId>hutool-core</artifactId>
			<version>5.6.5</version>
		</dependency>

方法摘要

方法描述
cn.hutool.core.date.LocalDateTimeUtil.now()
当前时间,默认时区
cn.hutool.core.date.LocalDateTimeUtil.of(java.time.Instant)
@link Instant转@link LocalDateTime,使用默认时区
cn.hutool.core.date.LocalDateTimeUtil.ofUTC(java.time.Instant)
@link Instant转@link LocalDateTime,使用UTC时区
cn.hutool.core.date.LocalDateTimeUtil.of(java.time.ZonedDateTime)
@link ZonedDateTime转@link LocalDateTime
cn.hutool.core.date.LocalDateTimeUtil.of(java.time.Instant, java.time.ZoneId)
@link Instant转@link LocalDateTime
cn.hutool.core.date.LocalDateTimeUtil.of(java.time.Instant, java.util.TimeZone)
@link Instant转@link LocalDateTime
cn.hutool.core.date.LocalDateTimeUtil.of(long)
毫秒转@link LocalDateTime,使用默认时区

注意:此方法使用默认时区,如果非UTC,会产生时间偏移

cn.hutool.core.date.LocalDateTimeUtil.ofUTC(long)
毫秒转@link LocalDateTime,使用UTC时区
cn.hutool.core.date.LocalDateTimeUtil.of(long, java.time.ZoneId)
毫秒转@link LocalDateTime,根据时区不同,结果会产生时间偏移
cn.hutool.core.date.LocalDateTimeUtil.of(long, java.util.TimeZone)
毫秒转@link LocalDateTime,结果会产生时间偏移
cn.hutool.core.date.LocalDateTimeUtil.of(java.util.Date)
@link Date转@link LocalDateTime,使用默认时区
cn.hutool.core.date.LocalDateTimeUtil.of(java.time.temporal.TemporalAccessor)
@link TemporalAccessor转@link LocalDateTime,使用默认时区
cn.hutool.core.date.LocalDateTimeUtil.ofDate(java.time.temporal.TemporalAccessor)
@link TemporalAccessor转@link LocalDate,使用默认时区
cn.hutool.core.date.LocalDateTimeUtil.parse(java.lang.CharSequence)
解析日期时间字符串为@link LocalDateTime,仅支持yyyy-MM-dd’T’HH:mm:ss格式,例如:2007-12-03T10:15:30
cn.hutool.core.date.LocalDateTimeUtil.parse(java.lang.CharSequence, java.time.format.DateTimeFormatter)
解析日期时间字符串为@link LocalDateTime,格式支持日期时间、日期、时间
cn.hutool.core.date.LocalDateTimeUtil.parse(java.lang.CharSequence, java.lang.String)
解析日期时间字符串为@link LocalDateTime
cn.hutool.core.date.LocalDateTimeUtil.parseDate(java.lang.CharSequence)
解析日期时间字符串为@link LocalDate,仅支持yyyy-MM-dd’T’HH:mm:ss格式,例如:2007-12-03T10:15:30
cn.hutool.core.date.LocalDateTimeUtil.parseDate(java.lang.CharSequence, java.time.format.DateTimeFormatter)
解析日期时间字符串为@link LocalDate,格式支持日期
cn.hutool.core.date.LocalDateTimeUtil.parseDate(java.lang.CharSequence, java.lang.String)
解析日期字符串为@link LocalDate
cn.hutool.core.date.LocalDateTimeUtil.formatNormal(java.time.LocalDateTime)
格式化日期时间为yyyy-MM-dd HH:mm:ss格式
cn.hutool.core.date.LocalDateTimeUtil.format(java.time.LocalDateTime, java.time.format.DateTimeFormatter)
格式化日期时间为指定格式
cn.hutool.core.date.LocalDateTimeUtil.format(java.time.LocalDateTime, java.lang.String)
格式化日期时间为指定格式
cn.hutool.core.date.LocalDateTimeUtil.formatNormal(java.time.LocalDate)
格式化日期时间为yyyy-MM-dd格式
cn.hutool.core.date.LocalDateTimeUtil.format(java.time.LocalDate, java.time.format.DateTimeFormatter)
格式化日期时间为指定格式
cn.hutool.core.date.LocalDateTimeUtil.format(java.time.LocalDate, java.lang.String)
格式化日期时间为指定格式
cn.hutool.core.date.LocalDateTimeUtil.offset(java.time.LocalDateTime, long, java.time.temporal.TemporalUnit)
日期偏移,根据field不同加不同值(偏移会修改传入的对象)
cn.hutool.core.date.LocalDateTimeUtil.between(java.time.LocalDateTime, java.time.LocalDateTime)
获取两个日期的差,如果结束时间早于开始时间,获取结果为负。

返回结果为@link Duration对象,通过调用toXXX方法返回相差单位

cn.hutool.core.date.LocalDateTimeUtil.between(java.time.LocalDateTime, java.time.LocalDateTime, java.time.temporal.ChronoUnit)
获取两个日期的差,如果结束时间早于开始时间,获取结果为负。

返回结果为时间差的long值

cn.hutool.core.date.LocalDateTimeUtil.betweenPeriod(java.time.LocalDate, java.time.LocalDate)
获取两个日期的表象时间差,如果结束时间早于开始时间,获取结果为负。

比如2011年2月1日,和2021年8月11日,日相差了10天,月相差6月

cn.hutool.core.date.LocalDateTimeUtil.beginOfDay(java.time.LocalDateTime)
修改为一天的开始时间,例如:2020-02-02 00:00:00,000
cn.hutool.core.date.LocalDateTimeUtil.endOfDay(java.time.LocalDateTime)
修改为一天的结束时间,例如:2020-02-02 23:59:59,999
cn.hutool.core.date.LocalDateTimeUtil.toEpochMilli(java.time.temporal.TemporalAccessor)
@link TemporalAccessor转换为 时间戳(从1970-01-01T00:00:00Z开始的毫秒数)

方法明细-now()

方法名称:cn.hutool.core.date.LocalDateTimeUtil.now()

方法描述

当前时间,默认时区

支持版本及以上

参数描述:

参数名描述

返回值:

@link LocalDateTime

参考案例:

		Assert.assertNotNull(LocalDateTimeUtil.now());
		System.out.println(LocalDateTimeUtil.now());

源码解析:

/**
 * 当前时间,默认时区
 *
 * @return @link LocalDateTime
 */
public static LocalDateTime now() 
   return LocalDateTime.now();

LocalDateTime.now() 的源码

public static LocalDateTime now() 
    return now(Clock.systemDefaultZone());

Clock.systemDefaultZone()

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

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

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

方法明细-of(java.time.Instant)

方法名称:cn.hutool.core.date.LocalDateTimeUtil.of(java.time.Instant)

方法描述

@link Instant转@link LocalDateTime,使用默认时区

支持版本及以上

参数描述:

参数名描述
Instant instant
instant @link Instant

返回值:

@link LocalDateTime

参考案例:

		String dateStr = "2020-01-23 12:23:56";
		final DateTime dt = DateUtil.parse(dateStr);

		LocalDateTime of = LocalDateTimeUtil.of(dt.toInstant());
		System.out.println(of);

源码解析:

public static LocalDateTime of(Instant instant) 
		return of(instant, ZoneId.systemDefault());
	

这里使用了默认时区,所以打印出来的日期时间是带时区的。

public static LocalDateTime of(Instant instant, ZoneId zoneId) 
   if (null == instant) 
      return null;
   
   return LocalDateTime.ofInstant(instant, ObjectUtil.defaultIfNull(zoneId, ZoneId.systemDefault()));

方法明细-ofUTC(java.time.Instant)

方法名称:cn.hutool.core.date.LocalDateTimeUtil.ofUTC(java.time.Instant)

方法描述

@link Instant转@link LocalDateTime,使用UTC时区

支持版本及以上

参数描述:

参数名描述
Instant instant
instant @link Instant

返回值:

@link LocalDateTime

参考案例:

		String dateStr = "2020-01-23T12:23:56";
		final DateTime dt = DateUtil.parse(dateStr);

		LocalDateTime of = LocalDateTimeUtil.ofUTC(dt.toInstant());
		Assert.assertEquals(dateStr, of.toString());
		System.out.println(of);

源码解析:

	public static LocalDateTime ofUTC(Instant instant) 
		return of(instant, ZoneId.of("UTC"));
	

这里使用了UTC 时区,然后调用下面的LocalDateTime.ofInstant

	public static LocalDateTime of(Instant instant, ZoneId zoneId) 
		if (null == instant) 
			return null;
		

		return LocalDateTime.ofInstant(instant, ObjectUtil.defaultIfNull(zoneId, ZoneId.systemDefault()));
	

方法明细-of(java.time.ZonedDateTime)

方法名称:cn.hutool.core.date.LocalDateTimeUtil.of(java.time.ZonedDateTime)

方法描述

@link ZonedDateTime转@link LocalDateTime

支持版本及以上

参数描述:

参数名描述
ZonedDateTime zonedDateTime
zonedDateTime @link ZonedDateTime

返回值:

@link LocalDateTime

参考案例:

		String dateStr = "2021-05-21T11:23:56";
		final DateTime dt = DateUtil.parse(dateStr);
		//使用默认时区
		LocalDateTime localDateTime = LocalDateTimeUtil.of(dt);
		System.out.println(localDateTime);
		ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.systemDefault());
		System.out.println(zonedDateTime);
		zonedDateTime = localDateTime.atZone( ZoneId.of("Asia/Shanghai"));
		System.out.println(zonedDateTime);
		LocalDateTime of = LocalDateTimeUtil.of(zonedDateTime);

		Assert.assertNotNull(of);
		Assert.assertEquals("2021-05-21T11:23:56", of.toString());

源码解析:

public static LocalDateTime of(ZonedDateTime zonedDateTime) 
		if (null == zonedDateTime) 
			return null;
		
		return zonedDateTime.toLocalDateTime();
	

这里先判断了参数 是否空值

然后调用zonedDateTime.toLocalDateTime()

我们知道zonedDateTimeLocalDateTime 是可以直接转化的

方法明细-of(java.time.Instant, java.time.ZoneId)

方法名称:cn.hutool.core.date.LocalDateTimeUtil.of(java.time.Instant, java.time.ZoneId)

方法描述

@link Instant转@link LocalDateTime

支持版本及以上

参数描述:

参数名描述
Instant instant
instant @link Instant
ZoneId zoneId
zoneId 时区

返回值:

@link LocalDateTime

参考案例:

		String dateStr = "2021-05-21T11:23:56";
		final DateTime dt = DateUtil.parse(dateStr);
		LocalDateTime of = LocalDateTimeUtil.of(dt.getTime(), ZoneId.of("UTC"));
		Assert.assertNotNull(of);
		Assert.assertEquals(dateStr, of.toString());

		of = LocalDateTimeUtil.of(dt.getTime(), ZoneId.of("Asia/Shanghai"));
		Assert.assertNotNull(of);
		Assert.assertEquals("2021-05-21T19:23:56", of.toString());

源码解析:

	public static LocalDateTime of(Instant instant, ZoneId zoneId) 
		if (null == instant) 
			return null;
		

		return LocalDateTime.ofInstant(instant, ObjectUtil.defaultIfNull(zoneId, ZoneId.systemDefault()));
	

这里先判断了参数 是否空值

然后执行了LocalDateTime.ofInstant(instant, ObjectUtil.defaultIfNull(zoneId, ZoneId.systemDefault()))

这里可拆分两部分:

1、ObjectUtil.defaultIfNull(zoneId, ZoneId.systemDefault())

2、LocalDateTime.ofInstant(instant, zoneId)

ObjectUtil.defaultIfNull(zoneId, ZoneId.systemDefault()) 的源码


	public static <T> T defaultIfNull(final T object, final T defaultValue) 
		return (null != object) ? object : defaultValue;
	

这个很好理解,判断值是否为null ,如果是返回默认值,如果不是,原值返回。

**LocalDateTime.ofInstant(instant, zoneId) ** 是jdk8自带的源生方法

方法明细-of(java.time.Instant, java.util.TimeZone)

方法名称:cn.hutool.core.date.LocalDateTimeUtil.of(java.time.Instant, java.util.TimeZone)

方法描述

@link Instant转@link LocalDateTime

支持版本及以上

参数描述:

参数名描述
Instant instant
instant @link Instant
TimeZone timeZone
timeZone 时区

返回值:

@link LocalDateTime

参考案例:

		String dateStr = "2021-05-21T11:23:56";
		// 通过转换获取的Instant为UTC时间
		Instant instant1 = DateUtil.parse(dateStr).toInstant();
		LocalDateTime localDateTime = LocalDateTimeUtil.of(instant1,TimeZone.getTimeZone(ZoneId.of("Asia/Shanghai")));
		Assert.assertEquals("2021-05-21T19:23:56", localDateTime.toString());
		System.out.println(localDateTime);

源码解析:

	public static LocalDateTime of(Instant instant, TimeZone timeZone) 
		if (null == instant) 
			return null;
		

		return of(instant, ObjectUtil.defaultIfNull(timeZone, TimeZone.getDefault()).toZoneId());
	

这里先判断了参数 是否空值

然后执行了LocalDateTime.ofInstant(timeZone, zoneId)

这里可拆分两部分:

1、ObjectUtil.defaultIfNull(timeZone, ObjectUtil.defaultIfNull(timeZone, TimeZone.getDefault()).toZoneId())

2、LocalDateTime.ofInstant(timeZone, zoneId)

ObjectUtil.defaultIfNull(timeZone, ObjectUtil.defaultIfNull(timeZone, TimeZone.getDefault()).toZoneId()) 的源码

	public static <T> T defaultIfNull(final T object, final T defaultValue) 
		return (null != object) ? object : defaultValue;
	

这个很好理解,判断值是否为null ,如果是返回默认值,如果不是,原值返回。

**LocalDateTime.ofInstant(instant, zoneId) ** 是jdk8自带的源生方法

方法明细-of(long)

方法名称:cn.hutool.core.date.LocalDateTimeUtil.of(long)

方法描述

毫秒转@link LocalDateTime,使用默认时区

注意:此方法使用默认时区,如果非UTC,会产生时间偏移

支持版本及以上

参数描述:

参数名描述
long epochMilli
epochMilli 从1970-01-01T00:00:00Z开始计数的毫秒数

返回值:

@link LocalDateTime

参考案例:

		String dateStr = "2021-05-22 10:23:56";
		Long time = DateUtil.parse(dateStr).getTime();
		// 使用默认时区
		LocalDateTime localDateTime = LocalDateTimeUtil.of(time);
		Assert.assertEquals("2021-05-22T10:23:56", localDateTime.toString());
		System.out.println(localDateTime);

源码解析:

	public static LocalDateTime of(long epochMilli) 
		return of(Instant.ofEpochMilli(epochMilli));
	

这是把long转成Instant

public static Instant ofEpochMilli(long epochMilli) 
        long secs = Math.floorDiv(epochMilli, 1000);
        int mos = (int)Math.floorMod(epochMilli, 1000);
        return create(secs, mos * 1000_000);
    

然后再调用of(Instant)

public static LocalDateTime of(Instant instant) 
   return of(instant, ZoneId.systemDefault());

方法明细-ofUTC(long)

方法名称:cn.hutool.core.date.LocalDateTimeUtil.ofUTC(long)

方法描述

毫秒转@link LocalDateTime,使用UTC时区

支持版本及以上

参数描述:

参数名描述
long epochMilli
epochMilli 从1970-01-01T00:00:00Z开始计数的毫秒数

返回值:

@link LocalDateTime

参考案例:

		String dateStr = "2021-05-22T10:23:56";
		Long time = DateUtil.parse(dateStr).getTime();
		// 使用UTC时区
		LocalDateTime localDateTime = LocalDateTimeUtil.ofUTC(time);
		Assert.assertEquals("2021-05-22T10:23:56", localDateTime.toString());
		System.out.println(localDateTime);

源码解析:

public static LocalDateTime ofUTC(long epochMilli) 
		return ofUTC(Instant.ofEpochMilli(epochMilli));
	

这是把long转成Instant

public static Instant ofEpochMilli(long epochMilli) 
        long secs = Math.floorDiv(epochMilli, 1000);
        int mos = (int)Math.floorMod(epochMilli, 1000);
        return create(secs, mos * 1000_000);
    

然后再调用ofUTC(Instant)

public static LocalDateTime ofUTC(Instant instant) 
		return of(instant, ZoneId.of("UTC"));
	

方法明细-of(long, java.time.ZoneId)

方法名称:cn.hutool.core.date.LocalDateTimeUtil.of(long, java.time.ZoneId)

方法描述

毫秒转@link LocalDateTime,根据时区不同,结果会产生时间偏移

支持版本及以上

参数描述:

参数名描述
long epochMilli
epochMilli 从1970-01-01T00:00:00Z开始计数的毫秒数
ZoneId zoneId
zoneId 时区

返回值:

@link LocalDateTime

参考案例:

		String dateStr = "2021-05-22T10:23:56";
		Long time = DateUtil.parse(dateStr).getTime();

		LocalDateTime localDateTime = LocalDateTimeUtil.of(time,ZoneId.of("Asia/Shanghai"));
		Assert.assertEquals("2021-05-22T18:23:56", localDateTime.toString());

源码解析:

/**
	 * 毫秒转@link LocalDateTime,根据时区不同,结果会产生时间偏移
	 *
	 * @param epochMilli 从1970-01-01T00:00:00Z开始计数的毫秒数
	 * @param zoneId     时区
	 * @return @link LocalDateTime
	 */
	public static LocalDateTime of(long epochMilli, ZoneId zoneId) 
		return of(Instant.ofEpochMilli(epochMilli), zoneId);
	

这是把long转成Instant

public static Insta

以上是关于高级JAVA开发必备技能:java8 新日期时间API(JSR-310:实战+源码分析)(JAVA 小虚竹)的主要内容,如果未能解决你的问题,请参考以下文章

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

高级JAVA开发必备技能:java8 新日期时间API(JSR-310:格式化和解析)(JAVA 小虚竹)

高级JAVA开发必备技能:java8 新日期时间API(JSR-310:ZoneId 时区和偏移量)(JAVA 小虚竹)

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

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

❤️高级JAVA开发必备技能❤️java8 新日期时间API(JSR-310:格式化和解析),2万字详解(JAVA 小虚竹,建议收藏)