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

如何自学黑客&网络安全

黑客零基础入门学习路线&规划

初级黑客
1、网络安全理论知识(2天)
①了解行业相关背景,前景,确定发展方向。
②学习网络安全相关法律法规。
③网络安全运营的概念。
④等保简介、等保规定、流程和规范。(非常重要)

2、渗透测试基础(一周)
①渗透测试的流程、分类、标准
②信息收集技术:主动/被动信息搜集、Nmap工具、Google Hacking
③漏洞扫描、漏洞利用、原理,利用方法、工具(MSF)、绕过IDS和反病毒侦察
④主机攻防演练:MS17-010、MS08-067、MS10-046、MS12-20等

3、操作系统基础(一周)
①Windows系统常见功能和命令
②Kali Linux系统常见功能和命令
③操作系统安全(系统入侵排查/系统加固基础)

4、计算机网络基础(一周)
①计算机网络基础、协议和架构
②网络通信原理、OSI模型、数据转发流程
③常见协议解析(HTTP、TCP/IP、ARP等)
④网络攻击技术与网络安全防御技术
⑤Web漏洞原理与防御:主动/被动攻击、DDOS攻击、CVE漏洞复现

5、数据库基础操作(2天)
①数据库基础
②SQL语言基础
③数据库安全加固

6、Web渗透(1周)
①HTML、CSS和JavaScript简介
②OWASP Top10
③Web漏洞扫描工具
④Web渗透工具:Nmap、BurpSuite、SQLMap、其他(菜刀、漏扫等)
恭喜你,如果学到这里,你基本可以从事一份网络安全相关的工作,比如渗透测试、Web 渗透、安全服务、安全分析等岗位;如果等保模块学的好,还可以从事等保工程师。薪资区间6k-15k

到此为止,大概1个月的时间。你已经成为了一名“脚本小子”。那么你还想往下探索吗?

如果你想要入坑黑客&网络安全,笔者给大家准备了一份:282G全网最全的网络安全资料包评论区留言即可领取!

7、脚本编程(初级/中级/高级)
在网络安全领域。是否具备编程能力是“脚本小子”和真正黑客的本质区别。在实际的渗透测试过程中,面对复杂多变的网络环境,当常用工具不能满足实际需求的时候,往往需要对现有工具进行扩展,或者编写符合我们要求的工具、自动化脚本,这个时候就需要具备一定的编程能力。在分秒必争的CTF竞赛中,想要高效地使用自制的脚本工具来实现各种目的,更是需要拥有编程能力.

如果你零基础入门,笔者建议选择脚本语言Python/PHP/Go/Java中的一种,对常用库进行编程学习;搭建开发环境和选择IDE,PHP环境推荐Wamp和XAMPP, IDE强烈推荐Sublime;·Python编程学习,学习内容包含:语法、正则、文件、 网络、多线程等常用库,推荐《Python核心编程》,不要看完;·用Python编写漏洞的exp,然后写一个简单的网络爬虫;·PHP基本语法学习并书写一个简单的博客系统;熟悉MVC架构,并试着学习一个PHP框架或者Python框架 (可选);·了解Bootstrap的布局或者CSS。

8、超级黑客
这部分内容对零基础的同学来说还比较遥远,就不展开细说了,附上学习路线。
img

网络安全工程师企业级学习路线

img
如图片过大被平台压缩导致看不清的话,评论区点赞和评论区留言获取吧。我都会回复的

视频配套资料&国内外网安书籍、文档&工具

当然除了有配套的视频,同时也为大家整理了各种文档和书籍资料&工具,并且已经帮大家分好类了。

img
一些笔者自己买的、其他平台白嫖不到的视频教程。
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以点击这里获取

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

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

image-20210919151333112

源码解析:

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

image-20210919152034372

源码解析:

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 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, zoneId)

上面的方法已经分析多次,就不再重复水字数。

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

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

方法描述

毫秒转{@link LocalDateTime},结果会产生时间偏移

支持版本及以上

参数描述:

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

返回值:

{@link LocalDateTime}

参考案例:

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

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

源码解析:

public static LocalDateTime of(long epochMilli, TimeZone timeZone) {
		return of(Instant.ofEpochMilli(epochMilli), timeZone);
	}

这是把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, timeZone)

上面的方法已经分析多次,就不再重复水字数。

方法明细-of(java.util.Date)

方法名称:cn.hutool.core.date.LocalDateTimeUtil.of(java.util.Date)

方法描述

{@link Date}转{@link LocalDateTime},使用默认时区

支持版本及以上

参数描述:

参数名描述
Date date
date Date对象

返回值:

{@link LocalDateTime}

参考案例:

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

源码解析:

	public static LocalDateTime of(Date date) {
		if (null == date) {
			return null;
		}

		if (date instanceof DateTime) {
			return of(date.toInstant(), ((DateTime) date).getZoneId());
		}
		return of(date.toInstant());
	}

此方法是把Date 强转为LocalDateTime

好习惯,先判断参数date是否为空

if (date instanceof DateTime) {
			return of(date.toInstant(), ((DateTime) date).getZoneId());
		}

这个DateTime 是hutool自己封装的对象,继承于Date ,封装了一些常用的方法

image-20210919153217935

如果不是前两者的话,就调用of(date.Instant)

方法明细-of(java.time.temporal.TemporalAccessor)

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

方法描述

{@link TemporalAccessor}转{@link LocalDateTime},使用默认时区

支持版本及以上

参数描述:

参数名描述
TemporalAccessor temporalAccessor
temporalAccessor {@link TemporalAccessor}

返回值:

{@link LocalDateTime}

参考案例:

		String dateStr = "2021-05-22T10:23:56";
		//使用默认时区
		TemporalAccessor temporalAccessor = DateTimeFormatter.ISO_DATE_TIME.parse(dateStr);
		LocalDateTime localDateTime = LocalDateTimeUtil.of(temporalAccessor);
		Assert.assertEquals("2021-05-22T10:23:56", localDateTime.toString());

源码解析:

	public static LocalDateTime of(TemporalAccessor temporalAccessor) {
		if (null == temporalAccessor) {
			return null;
		}

		if(temporalAccessor instanceof LocalDate){
			return ((LocalDate)temporalAccessor).atStartOfDay();
		}

		return LocalDateTime.of(
				TemporalAccessorUtil.get(temporalAccessor, ChronoField.YEAR),
				TemporalAccessorUtil.get(temporalAccessor, ChronoField.MONTH_OF_YEAR),
				TemporalAccessorUtil.get(temporalAccessor, ChronoField.DAY_OF_MONTH),
				TemporalAccessorUtil.get(temporalAccessor, ChronoField.HOUR_OF_DAY),
				TemporalAccessorUtil.get(temporalAccessor, ChronoField.MINUTE_OF_HOUR),
				TemporalAccessorUtil.get(temporalAccessor, ChronoField.SECOND_OF_MINUTE),
				TemporalAccessorUtil.get(temporalAccessor, ChronoField.NANO_OF_SECOND)
		);
	}

因为入参TemporalAccessor time的实现类常用的有如下几个(java8提供的):

  • LocalDateTime
  • LocalDate
  • LocalTime

好习惯,先判断参数temporalAccessor是否为空

然后判断temporalAccessor是否为LocalDate对象,如果是则调用LocalDate.atStartOfDay(),返回值是localDate+‘00:00’

//LocalDate
public LocalDateTime atStartOfDay() {
        return LocalDateTime.of(this, LocalTime.MIDNIGHT);
    }

/\*\*
 \* The time of midnight at the start of the day, '00:00'.
 \*/
public static final LocalTime MIDNIGHT;

public static LocalDateTime of(LocalDate date, LocalTime time) {
    Objects.requireNonNull(date, "date");
    Objects.requireNonNull(time, "time");
    return new LocalDateTime(date, time);
}

最后通过LocalDateTime.of 方法获取LocalDateTime对象的值。

但是博主发现一个问题,LocalTime 是没有年月日的,那怎么转化为LocalDateTime ,我们来写个demo看看效果

LocalTime localTime = LocalTime.now();
LocalDateTime localDateTime = LocalDateTimeUtil.of(localTime);
System.out.println(localDateTime);

image-20210919154701692

居然没有报错,这是为什么呢

return LocalDateTime.of(
				TemporalAccessorUtil.get(temporalAccessor, ChronoField.YEAR),
				TemporalAccessorUtil.get(temporalAccessor, ChronoField.MONTH_OF_YEAR),
				TemporalAccessorUtil.get(temporalAccessor, ChronoField.DAY_OF_MONTH),
				TemporalAccessorUtil.get(temporalAccessor, ChronoField.HOUR_OF_DAY),
				TemporalAccessorUtil.get(temporalAccessor, ChronoField.MINUTE_OF_HOUR),
				TemporalAccessorUtil.get(temporalAccessor, ChronoField.SECOND_OF_MINUTE),
				TemporalAccessorUtil.get(temporalAccessor, ChronoField.NANO_OF_SECOND)
		);

这里也是hutool自己封装的方法,都是调用**public static int get(TemporalAccessor temporalAccessor, TemporalField field) ** 源码如下

public static int get(TemporalAccessor temporalAccessor, TemporalField field) {
   if (temporalAccessor.isSupported(field)) {
      return temporalAccessor.get(field);
   }

   return (int)field.range().getMinimum();
}

这个代码很好理解,就是取temporalAccessor 对象对应的属性值,如果不存在,则取这个属性值的最小值。

断点看效果:

1、localtime是不存在year属性的

image-20210919155438622

2、取这个字段的最小值。

image-20210919155550186

其他字段获取方式也差不多。

方法明细-ofDate(java.time.temporal.TemporalAccessor)

方法名称:cn.hutool.core.date.LocalDateTimeUtil.ofDate(java.time.temporal.TemporalAccessor)

方法描述

{@link TemporalAccessor}转{@link LocalDate},使用默认时区

支持版本及以上

5.3.10

参数描述:

参数名描述
TemporalAccessor temporalAccessor
temporalAccessor {@link TemporalAccessor}

返回值:

{@link LocalDate}

参考案例:

		String dateStr = "2021-05-22T10:23:56";
		//使用默认时区
		TemporalAccessor temporalAccessor = DateTimeFormatter.ISO_DATE_TIME.parse(dateStr);
		LocalDate localDate = LocalDateTimeUtil.ofDate(temporalAccessor);
		Assert.assertEquals("2021-05-22", localDate.toString());

源码解析:

	public static LocalDate ofDate(TemporalAccessor temporalAccessor) {
		if (null == temporalAccessor) {
			return null;
		}

		if(temporalAccessor instanceof LocalDateTime){
			return ((LocalDateTime)temporalAccessor).toLocalDate();
		}

		return LocalDate.of(
				TemporalAccessorUtil.get(temporalAccessor, ChronoField.YEAR),
				TemporalAccessorUtil.get(temporalAccessor, ChronoField.MONTH_OF_YEAR),
				TemporalAccessorUtil.get(temporalAccessor, ChronoField.DAY_OF_MONTH)
		);
	}

因为入参TemporalAccessor time的实现类常用的有如下几个(java8提供的):

  • LocalDateTime
  • LocalDate
  • LocalTime

好习惯,先判断参数temporalAccessor是否为空

然后判断temporalAccessor是否为LocalDateTime对象,如果是则调用LocalDateTime.toLocalDate(),返回值是localDate,因为LocalDateTime=localDate+LocalTime

最后通过LocalDate.of 方法获取LocalDate对象的值。

方法明细-parse(java.lang.CharSequence)

方法名称:cn.hutool.core.date.LocalDateTimeUtil.parse(java.lang.CharSequence)

方法描述

解析日期时间字符串为{@link LocalDateTime},仅支持yyyy-MM-dd’T’HH:mm:ss格式,例如:2007-12-03T10:15:30

支持版本及以上

参数描述:

参数名描述
CharSequence text
text 日期时间字符串

返回值:

{@link LocalDateTime}

参考案例:

		final LocalDateTime localDateTime = LocalDateTimeUtil.parse("2020-01-23T12:23:56");
		Assert.assertEquals("2020-01-23T12:23:56", localDateTime.toString());

image-20210919160344393

源码解析:

	/\*\*
 \* 解析日期时间字符串为{@link LocalDateTime},仅支持yyyy-MM-dd'T'HH:mm:ss格式,例如:2007-12-03T10:15:30
 \*
 \* @param text 日期时间字符串
 \* @return {@link LocalDateTime}
 \*/
	public static LocalDateTime parse(CharSequence text) {
		return parse(text, (DateTimeFormatter)null);
	}

请看下面的源码分析。

方法明细-parse(java.lang.CharSequence, java.time.format.DateTimeFormatter)

方法名称:cn.hutool.core.date.LocalDateTimeUtil.parse(java.lang.CharSequence, java.time.format.DateTimeFormatter)

方法描述

解析日期时间字符串为{@link LocalDateTime},格式支持日期时间、日期、时间

支持版本及以上

参数描述:

参数名描述
CharSequence text
text 日期时间字符串 当formatter为null时,字符串要符合格式2020-01-23T12:23:56
DateTimeFormatter formatter
formatter 日期格式化器,预定义的格式见:{@link DateTimeFormatter}

返回值:

{@link LocalDateTime}

参考案例:

		final LocalDateTime localDateTime = LocalDateTimeUtil.parse("2020-01-23T12:23:56", DateTimeFormatter.ISO_DATE_TIME);
		Assert.assertEquals("2020-01-23T12:23:56", localDateTime.toString());
		System.out.println(localDateTime);

image-20210919160344393

源码解析:

	public static LocalDateTime parse(CharSequence text, DateTimeFormatter formatter) {
		if (null == text) {
			return null;
		}
		if (null == formatter) {
			return LocalDateTime.parse(text);
		}

		return of(formatter.parse(text));
	}

如果有同学对CharSequence 对象陌生的话,那对String 应该不会陌生,StringCharSequence 的实现接口

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    ...
    }

DateTimeFormatter 是jdk8提供的日期时间格式化器,用来替换我们的老朋友 simpledateformat

好习惯,先判断参数CharSequence是否为空

然后再判断参数DateTimeFormatter 是否为空,如果为空,则直接调用LocalDateTime.parse(text)

来看看源码

public static LocalDateTime parse(CharSequence text) {
    return parse(text, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
}

这里用的日期格式化字符串要像这种格式的:

such as ‘2011-12-03T10:15:30’

那如果传入的CharSequence参数不是这种格式的字符串,会是什么结果

//符合格式2020-01-23T12:23:56
LocalDateTime localDateTime = LocalDateTimeUtil.parse("2020-01-23T12:23:56", DateTimeFormatter.ISO_DATE_TIME);
Assert.assertEquals("2020-01-23T12:23:56", localDateTime.toString());
System.out.println(localDateTime);

//不符合格式的
DateTimeFormatter dateTimeFormatter = null;
localDateTime = LocalDateTimeUtil.parse("2020-01-23", dateTimeFormatter);
System.out.println(localDateTime);

执行结果,在预料之中,直接报错,这里是个坑,大家要注意

java.time.format.DateTimeParseException: Text ‘2020-01-23’ could not be parsed at index 10

image-20210919161934470

最后调用of(formatter.parse(text))

formatter.parse(text) 返回结果是TemporalAccessor,不一定是我们想要的LocalDateTime ,所以还要再通过of转一下

formatter.parse(text) 是原生JDK8自带的方法。

方法明细-parse(java.lang.CharSequence, java.lang.String)

方法名称:cn.hutool.core.date.LocalDateTimeUtil.parse(java.lang.CharSequence, java.lang.String)

方法描述

解析日期时间字符串为{@link LocalDateTime}

支持版本及以上

参数描述:

参数名描述
CharSequence text
text 日期时间字符串
String format
format 日期格式,类似于yyyy-MM-dd HH:mm:ss,SSS

返回值:

{@link LocalDateTime}

参考案例:

		final LocalDateTime localDateTime = LocalDateTimeUtil.parse("2020-01-23", DatePattern.NORM_DATE_PATTERN);
		Assert.assertEquals("2020-01-23T00:00", localDateTime.toString());

源码解析:

	public static LocalDateTime parse(CharSequence text, String format) {
		if (null == text) {
			return null;
		}

		DateTimeFormatter formatter = null;
		if(StrUtil.isNotBlank(format)){
			// 修复yyyyMMddHHmmssSSS格式不能解析的问题
			// fix issue#1082
			//see https://stackoverflow.com/questions/22588051/is-java-time-failing-to-parse-fraction-of-second
			// jdk8 bug at: https://bugs.openjdk.java.net/browse/JDK-8031085
			if(StrUtil.startWithIgnoreEquals(format, DatePattern.PURE_DATETIME_PATTERN)){
				final String fraction = StrUtil.removePrefix(format, DatePattern.PURE_DATETIME_PATTERN);
				if(ReUtil.isMatch("[S]{1,2}", fraction)){
					//将yyyyMMddHHmmssS、yyyyMMddHHmmssSS的日期统一替换为yyyyMMddHHmmssSSS格式,用0补
					text += StrUtil.repeat('0', 3-fraction.length());
				}
				formatter = new DateTimeFormatterBuilder()
						.appendPattern(DatePattern.PURE_DATETIME_PATTERN)
						.appendValue(ChronoField.MILLI_OF_SECOND, 3)
						.toFormatter();
			} else{
				formatter = DateTimeFormatter.ofPattern(format);
			}
		}

		return parse(text, formatter);
	}

养成好习惯,先判断参数CharSequence和format是否为空

这边针对jdk8的一个bug进行了兼容处理

1、在正常配置按照标准格式的字符串日期,是能够正常转换的。如果月,日,时,分,秒在不足两位的情况需要补0,否则的话会转换失败,抛出异常。
		DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
		LocalDateTime dt1 = LocalDateTime.parse("2021-7-20 23:46:43.946", DATE_TIME_FORMATTER);
		System.out.println(dt1);

会报错:

image-202107208183

java.time.format.DateTimeParseException: Text '2021-7-20 23:46:43.946' could not be parsed at index 5

分析原因:是格式字符串与实际的时间不匹配

“yyyy-MM-dd HH:mm:ss.SSS”

“2021-7-20 23:46:43.946”

中间的月份格式是MM,实际时间是7

解决方案:保持格式字符串与实际的时间匹配

	DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
		LocalDateTime dt1 = LocalDateTime.parse("2021-07-20 23:46:43.946", DATE_TIME_FORMATTER);
		System.out.println(dt1);

image-20210720504067

方法明细-parseDate(java.lang.CharSequence)

方法名称:cn.hutool.core.date.LocalDateTimeUtil.parseDate(java.lang.CharSequence)

方法描述

解析日期时间字符串为{@link LocalDate},仅支持yyyy-MM-dd’T’HH:mm:ss格式,例如:2007-12-03T10:15:30

支持版本及以上

5.3.10

参数描述:

参数名描述
CharSequence text
text 日期时间字符串

返回值:

{@link LocalDate}

参考案例:

		LocalDate localDate = LocalDateTimeUtil.parseDate("2020-01-23");		Assert.assertEquals("2020-01-23", localDate.toString());

源码解析:

	/\*\*
 \* 解析日期时间字符串为{@link LocalDate},仅支持yyyy-MM-dd'T'HH:mm:ss格式,例如:2007-12-03T10:15:30
 \*
 \* @param text 日期时间字符串
 \* @return {@link LocalDate}
 \* @since 5.3.10
 \*/
	public static LocalDate parseDate(CharSequence text) {
		return parseDate(text, (DateTimeFormatter)null);
	}

请看下面的源码分析。

方法明细-parseDate(java.lang.CharSequence, java.time.format.DateTimeFormatter)

方法名称:cn.hutool.core.date.LocalDateTimeUtil.parseDate(java.lang.CharSequence, java.time.format.DateTimeFormatter)

方法描述

解析日期时间字符串为{@link LocalDate},格式支持日期

支持版本及以上

5.3.10

参数描述:

参数名描述
CharSequence text
text 日期时间字符串
DateTimeFormatter formatter
formatter 日期格式化器,预定义的格式见:{@link DateTimeFormatter}

返回值:

{@link LocalDate}

参考案例:

		final LocalDateTime localDateTime = LocalDateTimeUtil.parse("12:23:56", DatePattern.NORM_TIME_PATTERN);
		Assert.assertEquals("12:23:56", localDateTime.toLocalTime().toString());

源码解析:

	public static LocalDate parseDate(CharSequence text, DateTimeFormatter formatter) {
		if (null == text) {
			return null;
		}
		if (null == formatter) {
			return LocalDate.parse(text);
		}

		return ofDate(formatter.parse(text));
	}

如果有同学对CharSequence 对象陌生的话,那对String 应该不会陌生,StringCharSequence 的实现接口

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    ...
    }

DateTimeFormatter 是jdk8提供的日期时间格式化器,用来替换我们的老朋友 simpledateformat

好习惯,先判断参数CharSequence是否为空

然后再判断参数DateTimeFormatter 是否为空,如果为空,则直接调用LocalDate.parse(text)

来看看源码

 public static LocalDate parse(CharSequence text) {
        return parse(text, DateTimeFormatter.ISO_LOCAL_DATE);
    }

这里用的日期格式化字符串要像这种格式的:

such as ‘2011-12-03’

最后调用of(formatter.parse(text))

formatter.parse(text) 返回结果是TemporalAccessor,不一定是我们想要的LocalDate ,所以还要再通过of转一下

formatter.parse(text) 是原生JDK8自带的方法。

方法明细-parseDate(java.lang.CharSequence, java.lang.String)

方法名称:cn.hutool.core.date.LocalDateTimeUtil.parseDate(java.lang.CharSequence, java.lang.String)

方法描述

解析日期字符串为{@link LocalDate}

支持版本及以上

参数描述:

参数名描述
CharSequence text
text 日期字符串
String format
format 日期格式,类似于yyyy-MM-dd

返回值:

{@link LocalDateTime}

参考案例:

		//第一个参数和第二个参数格式保持一致
		LocalDate localDate = LocalDateTimeUtil.parseDate("2020-01-23 12:23:56","yyyy-MM-dd hh:mm:ss");
		Assert.assertEquals("2020-01-23", localDate.toString());
		 localDate = LocalDateTimeUtil.parseDate("2020/01/23 12:23:56","yyyy/MM/dd hh:mm:ss");
		Assert.assertEquals("2020-01-23", localDate.toString());

源码解析:

	public static LocalDate parseDate(CharSequence text, String format) {
		if (null == text) {
			return null;
		}
		return parseDate(text, DateTimeFormatter.ofPattern(format));
	}

请看上面的源码分析。

方法明细-formatNormal(java.time.LocalDateTime)

方法名称:cn.hutool.core.date.LocalDateTimeUtil.formatNormal(java.time.LocalDateTime)

方法描述

格式化日期时间为yyyy-MM-dd HH:mm:ss格式

支持版本及以上

5.3.11

参数描述:

参数名描述
LocalDateTime time
time {@link LocalDateTime}

返回值:

格式化后的字符串

参考案例:

        final LocalDateTime localDateTime = LocalDateTimeUtil.parse("2020-01-23T12:23:56");
	    String	format = LocalDateTimeUtil.formatNormal(localDateTime);
		Assert.assertEquals("2020-01-23 12:23:56", format);

源码解析:

	/\*\*
 \* 格式化日期时间为yyyy-MM-dd HH:mm:ss格式
 \*
 \* @param time {@link LocalDateTime}
 \* @return 格式化后的字符串
 \* @since 5.3.11
 \*/
	public static String formatNormal(LocalDateTime time) {
		return format(time, DatePattern.NORM_DATETIME_FORMATTER);
	}

//------------------------------
public static String format(LocalDateTime time, DateTimeFormatter formatter) {
		return TemporalAccessorUtil.format(time, formatter);
	}

TemporalAccessorUtil 类是hutool封装的工具类,看下面的源码,也是比较好理解的。

//TemporalAccessorUtil
/\*\*
 \* 格式化日期时间为指定格式
 \*
 \* @param time {@link TemporalAccessor}
 \* @param formatter 日期格式化器,预定义的格式见:{@link DateTimeFormatter}
 \* @return 格式化后的字符串
 \* @since 5.3.10
 \*/
public static String format(TemporalAccessor time, DateTimeFormatter formatter) {
   if (null == time) {
      return null;
   }

   if(null == formatter){
      formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
   }


   try {
      return formatter.format(time);
   } catch (UnsupportedTemporalTypeException e){
      if(time instanceof LocalDate && e.getMessage().contains("HourOfDay")){
         // 用户传入LocalDate,但是要求格式化带有时间部分,转换为LocalDateTime重试
         return formatter.format(((LocalDate) time).atStartOfDay());
      }else if(time instanceof LocalTime && e.getMessage().contains("YearOfEra")){
         // 用户传入LocalTime,但是要求格式化带有日期部分,转换为LocalDateTime重试
         return formatter.format(((LocalTime) time).atDate(LocalDate.now()));
      }
      throw e;
   }
}

养成好习惯,先判断参数TemporalAccessorDateTimeFormatter 是否为空

如果DateTimeFormatter 为空,则给默认值DateTimeFormatter.ISO_LOCAL_DATE_TIME

such as ‘2011-12-03T10:15:30’

然后调用格式化方法formatter.format(time) 如果time 不是LocalDateTime 对象,则会报错,然后在catch里做了兼容处理,对LocalDateLocalTime 对象可以进行格式化处理,其他的直接返回异常。

方法明细-format(java.time.LocalDateTime, java.time.format.DateTimeFormatter)

方法名称:cn.hutool.core.date.LocalDateTimeUtil.format(java.time.LocalDateTime, java.time.format.DateTimeFormatter)

方法描述

格式化日期时间为指定格式

支持版本及以上

参数描述:

参数名描述
LocalDateTime time
time {@link LocalDateTime}
DateTimeFormatter formatter
formatter 日期格式化器,预定义的格式见:{@link DateTimeFormatter}

返回值:

格式化后的字符串

参考案例:

		LocalDateTime localDateTime = LocalDateTimeUtil.parse("2020-01-23T12:23:56");
		String format = LocalDateTimeUtil.format(localDateTime, DateTimeFormatter.ISO_DATE_TIME);
		Assert.assertEquals("2020-01-23T12:23:56", format);

源码解析:

	/\*\*
 \* 格式化日期时间为指定格式
 \*
 \* @param time {@link LocalDateTime}
 \* @param formatter 日期格式化器,预定义的格式见:{@link DateTimeFormatter}
 \* @return 格式化后的字符串
 \*/
	public static String format(LocalDateTime time, DateTimeFormatter formatter) {
		return TemporalAccessorUtil.format(time, formatter);
	}

请看上面的源码分析。

方法明细-format(java.time.LocalDateTime, java.lang.String)

方法名称:cn.hutool.core.date.LocalDateTimeUtil.format(java.time.LocalDateTime, java.lang.String)

方法描述

格式化日期时间为指定格式

支持版本及以上

参数描述:

参数名描述
LocalDateTime time
time {@link LocalDateTime}
String format
format 日期格式,类似于yyyy-MM-dd HH:mm:ss,SSS

返回值:

格式化后的字符串

参考案例:

		final LocalDateTime localDateTime = LocalDateTimeUtil.parse("2020-01-23T12:23:56");
		String format = LocalDateTimeUtil.format(localDateTime, DatePattern.NORM_DATETIME_PATTERN);
		Assert.assertEquals("2020-01-23 12:23:56", format);

源码解析:

	public static String format(LocalDateTime time, String format) {
		if (null == time) {
			return null;
		}
		return format(time, DateTimeFormatter.ofPattern(format));
	}

DateTimeFormatter.ofPattern(format) 执行完会返回DateTimeFormatter

然后会调用 format(time, DateTimeFormatter 方法

请看上面的源码分析。

方法明细-formatNormal(java.time.LocalDate)

方法名称:cn.hutool.core.date.LocalDateTimeUtil.formatNormal(java.time.LocalDate)

方法描述

格式化日期时间为yyyy-MM-dd格式

支持版本及以上

5.3.11

参数描述:

参数名描述
LocalDate date
date {@link LocalDate}

返回值:

格式化后的字符串

参考案例:

		final LocalDate date = LocalDate.parse("2020-01-23");
		String format = LocalDateTimeUtil.format(date, DatePattern.NORM_DATE_PATTERN);
		Assert.assertEquals("2020-01-23", format);

		format = LocalDateTimeUtil.formatNormal(date);
		Assert.assertEquals("2020-01-23", format);

源码解析:

public static String formatNormal(LocalDate date) {
		return format(date, DatePattern.NORM_DATE_FORMATTER);
	}

请看上面的源码分析。

方法明细-format(java.time.LocalDate, java.time.format.DateTimeFormatter)

方法名称:cn.hutool.core.date.LocalDateTimeUtil.format(java.time.LocalDate, java.time.format.DateTimeFormatter)

方法描述

格式化日期时间为指定格式

支持版本及以上

5.3.10

参数描述:

参数名描述
LocalDate date
date {@link LocalDate}
DateTimeFormatter formatter
formatter 日期格式化器,预定义的格式见:{@link DateTimeFormatter}

返回值:

格式化后的字符串

参考案例:

		final LocalDate date = LocalDate.parse("2021-05-22");
		String format = LocalDateTimeUtil.format(date, DateTimeFormatter.ISO_DATE);
		Assert.assertEquals("2021-05-22", format);

源码解析:

	public static String format(LocalDate date, DateTimeFormatter formatter) {
		return TemporalAccessorUtil.format(date, formatter);
	}

请看上面的源码分析。

方法明细-format(java.time.LocalDate, java.lang.String)

方法名称:cn.hutool.core.date.LocalDateTimeUtil.format(java.time.LocalDate, java.lang.String)

方法描述

格式化日期时间为指定格式

支持版本及以上

5.3.10

参数描述:

参数名描述
LocalDate date
date {@link LocalDate}
String format
format 日期格式,类似于yyyy-MM-dd

返回值:

格式化后的字符串

参考案例:

		final LocalDate date = LocalDate.parse("2020-01-23");
		String format = LocalDateTimeUtil.format(date, DatePattern.NORM_DATE_PATTERN);
		Assert.assertEquals("2020-01-23", format);


源码解析:

	public static String format(LocalDate date, String format) {
		if (null == date) {
			return null;
		}
		return format(date, DateTimeFormatter.ofPattern(format));
	}

请看上面的源码分析。

方法明细-offset(java.time.LocalDateTime, long, java.time.temporal.TemporalUnit)

方法名称:cn.hutool.core.date.LocalDateTimeUtil.offset(java.time.LocalDateTime, long, java.time.temporal.TemporalUnit)

方法描述

日期偏移,根据field不同加不同值(偏移会修改传入的对象)

支持版本及以上

参数描述:

参数名描述
LocalDateTime time
time {@link LocalDateTime}
long number
number 偏移量,正数为向后偏移,负数为向前偏移
TemporalUnit field
field 偏移单位,见{@link ChronoUnit},不能为null

返回值:

偏移后的日期时间

参考案例:

		final LocalDateTime localDateTime = LocalDateTimeUtil.parse("2020-01-23T12:23:56");
		LocalDateTime offset = LocalDateTimeUtil.offset(localDateTime, 1, ChronoUnit.DAYS);
		// 非同一对象
		Assert.assertNotSame(localDateTime, offset);

		Assert.assertEquals("2020-01-24T12:23:56", offset.toString());

源码解析:

	/\*\*
 \* 日期偏移,根据field不同加不同值(偏移会修改传入的对象)
 \*
 \* @param time {@link LocalDateTime}
 \* @param number 偏移量,正数为向后偏移,负数为向前偏移
 \* @param field 偏移单位,见{@link ChronoUnit},不能为null
 \* @return 偏移后的日期时间
 \*/
	public static LocalDateTime offset(LocalDateTime time, long number, TemporalUnit field) {
		if (null == time) {
			return null;
		}

		return time.plus(number, field);
	}


time.plus(number, field) 是jdk8提供的方法

	LocalDateTime localDateTime = LocalDateTime.of(2021, 8, 30, 23, 14, 20);
	LocalDateTime offset = localDateTime.plus(1, ChronoUnit.DAYS);
	// 非同一对象
	Assert.assertNotSame(localDateTime, offset);
	System.out.println(offset);

image-20210831233938785

方法明细-between(java.time.LocalDateTime, java.time.LocalDateTime)

方法名称:cn.hutool.core.date.LocalDateTimeUtil.between(java.time.LocalDateTime, java.time.LocalDateTime)

方法描述

获取两个日期的差,如果结束时间早于开始时间,获取结果为负。

返回结果为{@link Duration}对象,通过调用toXXX方法返回相差单位 ## 支持版本及以上

参数描述:

参数名描述
LocalDateTime startTimeInclude
startTimeInclude 开始时间(包含)
LocalDateTime endTimeExclude
endTimeExclude 结束时间(不包含)

返回值:

给大家的福利

零基础入门

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

同时每个成长路线对应的板块都有配套的视频提供:

在这里插入图片描述

因篇幅有限,仅展示部分资料

网络安全面试题

绿盟护网行动

还有大家最喜欢的黑客技术

网络安全源码合集+工具包

所有资料共282G,朋友们如果有需要全套《网络安全入门+黑客进阶学习资源包》,可以扫描下方二维码领取(如遇扫码问题,可以在评论区留言领取哦)~

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以点击这里获取

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

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值