2hutool源码分析:DateUtil(时间工具类)-常用的时间类型Date,DateTime,Calendar和TemporalAccessor(LocalDateTime)转换

《hutool源码解析》 专栏收录该内容
8 篇文章 4 订阅
技术活,该赏
关注+一键三连(点赞,评论,收藏)再看,养成好习惯

看本篇文章前,建议先对java源码的日期和时间有一定的了解,如果不了解的话,可以先看这篇文章:

万字博文教你搞懂java源码的日期和时间相关用法

关联文章:
hutool实战(带你掌握里面的各种工具)目录

2hutool实战:DateUtil-常用的时间类型转换


源码分析目的

知其然,知其所以然

项目引用

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

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

方法名称:DateUtil.date(java.util.Date)

方法描述

{@link Date}类型时间转为{@link DateTime}<br>
如果date本身为DateTime对象,则返回强转后的对象,否则新建一个DateTime对象

源码分析一

/**
	 * {@link Date}类型时间转为{@link DateTime}<br>
	 * 如果date本身为DateTime对象,则返回强转后的对象,否则新建一个DateTime对象
	 *
	 * @param date Long类型Date(Unix时间戳)
	 * @return 时间对象
	 * @since 3.0.7
	 */
	public static DateTime date(Date date) {
		if (date instanceof DateTime) {
			return (DateTime) date;
		}
		return dateNew(date);
	}

判断传入的date是否是DateTime类型,如果是,直接转换成DateTime对象

如果不是,则执行DateUtil.dateNew((date)

方法名称:DateUtil.DateUtil.dateNew(java.util.Date)

方法描述

根据已有{@link Date} 产生新的{@link DateTime}对象

源码分析一

/**
	 * 根据已有{@link Date} 产生新的{@link DateTime}对象
	 *
	 * @param date Date对象
	 * @return {@link DateTime}对象
	 * @since 4.3.1
	 */
	public static DateTime dateNew(Date date) {
		return new DateTime(date);
	}

---------------------------------
    //DateTime 类
    /**
	 * 给定日期的构造
	 *
	 * @param date 日期
	 */
	public DateTime(Date date) {
		this(
				date,//
				(date instanceof DateTime) ? ((DateTime) date).timeZone : TimeZone.getDefault()
		);
	}

代码里写了一个多目运算,(date instanceof DateTime) ? ((DateTime) date).timeZone : TimeZone.getDefault()

传入的date是否是DateTime类型,如果是,直接取DateTime对象的时区,如果不是,取系统默认时区。

然后调用这个方法DateTime(Date date, TimeZone timeZone)

  //DateTime 类
/**
	 * 给定日期的构造
	 *
	 * @param date     日期
	 * @param timeZone 时区
	 * @since 4.1.2
	 */
	public DateTime(Date date, TimeZone timeZone) {
		this(ObjectUtil.defaultIfNull(date, new Date()).getTime(), timeZone);
	}

ObjectUtil.defaultIfNull(date, new Date()).getTime()

要拆成2个调用

1、ObjectUtil.defaultIfNull(date, new Date())

2、Date.getTime()

ObjectUtil.defaultIfNull是Hutool封装的一个工具类,用来判断数据对象是否为null,如果是,返回默认值

源码如下

/**
	 * 如果给定对象为{@code null}返回默认值
	 *
	 * <pre>
	 * ObjectUtil.defaultIfNull(null, null)      = null
	 * ObjectUtil.defaultIfNull(null, "")        = ""
	 * ObjectUtil.defaultIfNull(null, "zz")      = "zz"
	 * ObjectUtil.defaultIfNull("abc", *)        = "abc"
	 * ObjectUtil.defaultIfNull(Boolean.TRUE, *) = Boolean.TRUE
	 * </pre>
	 *
	 * @param <T>          对象类型
	 * @param object       被检查对象,可能为{@code null}
	 * @param defaultValue 被检查对象为{@code null}返回的默认值,可以为{@code null}
	 * @return 被检查对象为{@code null}返回默认值,否则返回原值
	 * @since 3.0.7
	 */
	public static <T> T defaultIfNull(final T object, final T defaultValue) {
		return (null != object) ? object : defaultValue;
	}

最后会调用这个方法

	/**
	 * 给定日期毫秒数的构造
	 *
	 * @param timeMillis 日期毫秒数
	 * @param timeZone   时区
	 * @since 4.1.2
	 */
	public DateTime(long timeMillis, TimeZone timeZone) {
		super(timeMillis);
		this.timeZone = ObjectUtil.defaultIfNull(timeZone, TimeZone.getDefault());
	}

从**DateTime(long timeMillis, TimeZone timeZone)中源码中,可看出,在Date(long date)**基础上,多加了timeZone的赋值。

image-20210706213821993

方法名称:DateUtil.DateUtil.date(long)

方法描述

Long类型时间转为{@link DateTime}<br>
只支持毫秒级别时间戳,如果需要秒级别时间戳,请自行×1000

源码分析一

/**
	 * Long类型时间转为{@link DateTime}<br>
	 * 只支持毫秒级别时间戳,如果需要秒级别时间戳,请自行×1000
	 *
	 * @param date Long类型Date(Unix时间戳)
	 * @return 时间对象
	 */
	public static DateTime date(long date) {
		return new DateTime(date);
	}

-------------------------------------
    /**
	 * 给定日期毫秒数的构造
	 *
	 * @param timeMillis 日期毫秒数
	 * @since 4.1.2
	 */
	public DateTime(long timeMillis) {
		this(timeMillis, TimeZone.getDefault());
	}

从**DateTime(long timeMillis, TimeZone timeZone)中源码中,可看出,在Date(long date)**基础上,多加了timeZone的赋值。

image-20210706213821993

方法名称:DateUtil.DateUtil.date(java.util.Calendar)

方法描述

{@link Calendar}类型时间转为{@link DateTime}<br>
始终根据已有{@link Calendar} 产生新的{@link DateTime}对象

源码分析一

	/**
	 * {@link Calendar}类型时间转为{@link DateTime}<br>
	 * 始终根据已有{@link Calendar} 产生新的{@link DateTime}对象
	 *
	 * @param calendar {@link Calendar}
	 * @return 时间对象
	 */
	public static DateTime date(Calendar calendar) {
		return new DateTime(calendar);
	}

----------------------------
    //DateTime类	
    /**
	 * 给定日期的构造
	 *
	 * @param calendar {@link Calendar}
	 */
	public DateTime(Calendar calendar) {
		this(calendar.getTime(), calendar.getTimeZone());
		this.setFirstDayOfWeek(Week.of(calendar.getFirstDayOfWeek()));
	}

**this(calendar.getTime(), calendar.getTimeZone());**就是调用 DateTime(Date date, TimeZone timeZone)

this.setFirstDayOfWeek(Week.of(calendar.getFirstDayOfWeek()));

实际上是调用了三个步骤:

1、calendar.getFirstDayOfWeek() 获取calendarWeekIntValue(一周的第一天)

2、Week.of(calendar.getFirstDayOfWeek()) -->Week of(int calendarWeekIntValue) 获取星期对应的枚举值

image-202107127917619

3、this.setFirstDayOfWeek(Week.of(calendar.getFirstDayOfWeek())) -->setFirstDayOfWeek(Week firstDayOfWeek) 给DateTime对象设置一周的第一天参数的值。

/**
	 * 设置一周的第一天<br>
	 * JDK的Calendar中默认一周的第一天是周日,Hutool中将此默认值设置为周一<br>
	 * 设置一周的第一天主要影响{@link #weekOfMonth()}和{@link #weekOfYear()} 两个方法
	 *
	 * @param firstDayOfWeek 一周的第一天
	 * @return this
	 * @see #weekOfMonth()
	 * @see #weekOfYear()
	 */
	public DateTime setFirstDayOfWeek(Week firstDayOfWeek) {
		this.firstDayOfWeek = firstDayOfWeek;
		return this;
	}

方法名称:DateUtil.DateUtil.date(java.time.temporal.TemporalAccessor)

方法描述

{@link TemporalAccessor}类型时间转为{@link DateTime}<br>
始终根据已有{@link TemporalAccessor} 产生新的{@link DateTime}对象

源码分析一

/**
	 * {@link TemporalAccessor}类型时间转为{@link DateTime}<br>
	 * 始终根据已有{@link TemporalAccessor} 产生新的{@link DateTime}对象
	 *
	 * @param temporalAccessor {@link TemporalAccessor},常用子类: {@link LocalDateTime}、 LocalDate
	 * @return 时间对象
	 * @since 5.0.0
	 */
	public static DateTime date(TemporalAccessor temporalAccessor) {
		return new DateTime(temporalAccessor);
	}
----------------------------------------------
    //DateTime 对象
    /**
	 * 给定日期TemporalAccessor的构造
	 *
	 * @param temporalAccessor {@link TemporalAccessor} 对象
	 * @since 5.0.0
	 */
	public DateTime(TemporalAccessor temporalAccessor) {
		this(DateUtil.toInstant(temporalAccessor));
	}

**this(DateUtil.toInstant(temporalAccessor));**这里调用了两个步骤

1、DateUtil.toInstant(temporalAccessor) TemporalAccessor 对象转为Instant对象

2、this(DateUtil.toInstant(temporalAccessor)); —>DateTime(Instant instant)

	/**
	 * 给定日期Instant的构造
	 *
	 * @param instant {@link Instant} 对象
	 * @since 5.0.0
	 */
	public DateTime(Instant instant) {
		this(instant.toEpochMilli());
	}
	
	----------------------
	/**
	 * 给定日期毫秒数的构造
	 *
	 * @param timeMillis 日期毫秒数
	 * @since 4.1.2
	 */
	public DateTime(long timeMillis) {
		this(timeMillis, TimeZone.getDefault());
	}

万变不离其宗,看,又绕回来了

©️2022 CSDN 皮肤主题:技术工厂 设计师:CSDN官方博客 返回首页

打赏作者

小虚竹

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值