前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >hutool官网(hutool好用吗)

hutool官网(hutool好用吗)

作者头像
全栈程序员站长
发布2022-07-28 21:19:30
17.6K0
发布2022-07-28 21:19:30
举报

大家好,又见面了,我是你们的朋友全栈君。

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

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

关联文章:

hutool实战(带你掌握里面的各种工具)目录

4hutool实战:DateUtil-格式化时间

源码分析目的

知其然,知其所以然

项目引用

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

方法名称:DateUtil.formatLocalDateTime(java.time.LocalDateTime)

方法描述

格式化日期时间<br> 格式 yyyy-MM-dd HH:mm:ss

源码分析一

首先formatLocalDateTime方法的入参是LocalDateTime(Java8支持的日期时间类,是线程安全的)

然后调用LocalDateTimeUtil.formatNormal(localDateTime)

跟代码,发现DatePattern.NORM_DATETIME_FORMATTER的日期时间格式为:

然后会调用format(LocalDateTime time, DateTimeFormatter formatter),DateTimeFormatter 这个也是(Java8支持的日期格式化器类,是线程安全的)。

hutool这里做了很好的示范,使用DateTimeFormatter替换了SimpleDateFormat(线程不安全的)。

为什么SimpleDateFormat是线程不安全的,请看万字博文教你搞懂java源码的日期和时间相关用法

然后我们继续往下深挖TemporalAccessorUtil.format(time, formatter)

最前面加了两个入参判空处理,time为null时,返回null;formatter为null时,给格式默认值,eg:2011-12-03T10:15:30

image-20210725113946673
image-20210725113946673

然后执行formatter.format(time)相当于是DateTimeFormatter.format(LocalDateTime)。这样就格式化成功了。

值得一说的是**TemporalAccessorUtil.format(TemporalAccessor time, DateTimeFormatter formatter)**里面有加异常处理机制

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

  • LocalDateTime
  • LocalDate
  • LocalTime

在进行日期时间转化时,日期时间和要转化的格式化字符串要对应上,不然会抛出异常,所以做了如上的补救措施。

方法名称:DateUtil.format(java.time.LocalDateTime, java.lang.String)

方法描述

根据特定格式格式化日期

源码分析一

首先:hutool提供了常用的日期时间格式

image-20210725115905355
image-20210725115905355

然后:调用LocalDateTimeUtil.format(localDateTime, format)

源码**format(time, DateTimeFormatter.ofPattern(format))**可以拆解成两部分:

  • DateTimeFormatter.ofPattern(format)
  • format(LocalDateTime time, DateTimeFormatter formatter)

第一部分:**DateTimeFormatter.ofPattern(format)**是把字符串日期时间格式转化为日期时间格式化对象DateTimeFormatter ;

注意DateTimeFormatter.ofPattern(format)的用法是有的(代码详解–>万字博文教你搞懂java源码的日期和时间相关用法):

  1. 在正常配置按照标准格式的字符串日期,是能够正常转换的。如果月,日,时,分,秒在不足两位的情况需要补0,否则的话会转换失败,抛出异常。
  2. YYYY和DD谨慎使用

第二部分,format(LocalDateTime time, DateTimeFormatter formatter)上面有介绍了,这里就不水字了。

方法名称:DateUtil.format(java.util.Date, java.text.DateFormat)

方法描述

根据特定格式格式化日期

源码分析一

从代码中**format(Date date, String format)**方法提供了两个入参,一个是Date 类型的 被格式化的日期和要日期格式的字符串。这是为了兼容java8之前的旧日期时间API提供的方法

方法内首先对两个参数加了判空处理。

然后判断时间是否是hutool的DateTime对象,如果是,则获取时区TimeZone

接着调用format(date, newSimpleFormat(format, null, timeZone)),可拆解成两部分:

  • newSimpleFormat(format, null, timeZone),获取SimpleDateFormat对象(注:此方法是非线程安全的)
  • format(Date date, DateFormat format) 根据特定格式格式化日期

首先:**newSimpleFormat(format, null, timeZone)**代码详解:

如果**format(Date date, String format)输入的是Date对象的时间,那format(date, newSimpleFormat(format, null, timeZone))**具象化后,是这样的:format(date, newSimpleFormat(format, null, null))

然后new了一个SimpleDateFormat对象。并设置了时区和设置了setLenient,这个方法的含义是是否严格解析日期。setLenient设置为false时,就是严格解析日期:会严格按照日期时间格式,java不会帮忙计算,直接抛出异常。

image-20210725122714337
image-20210725122714337

然后**format(Date date, DateFormat format) **代码分析:

对两个入参进行了判空处理。然后调用SimpleDateFormat.format(date),这是java8之前就有提供的方法。

方法名称:DateUtil.format(java.util.Date, java.time.format.DateTimeFormatter)(方法有问题,已反馈,官方已修正)

方法描述

根据特定格式格式化日期

源码分析一

首先对两个入参做了判空处理。

然后,执行了format.format(date.toInstant()),代码可拆解成两部分:

  • date.toInstant():返回Instant对象
  • DateTimeFormatter.format(Instant):java8提供的格式化日期时间的方法

代码**DateTimeFormatter.format(Instant)**是怎么处理的呢?

首先new了个StringBuilder对象,用来拼接字符串;

然后调用**formatTo(temporal, buf)**方法

**formatTo(temporal, buf)**方法也是先判断两个入参空处理。

然后,Instant对象被封装在一个新new的DateTimePrintContext对象

运行demo有问题,进行排查

image-20210725195348793
image-20210725195348793

到这里已经是jdk的源码了DateTimeFormatter.format

image-20210725195424950
image-20210725195424950
image-20210725195522610
image-20210725195522610
image-20210725195636339
image-20210725195636339

从上面可知,会调用 NumberPrinterParser.format() NumberPrinterParser是在DateTimeFormatterBuilder类中的。

image-20210725195947802
image-20210725195947802

到这一步会报错

image-20210725200153850
image-20210725200153850

为什么会报错呢,我们来看下context.getValue(field)发生了什么:

image-20210725200349650
image-20210725200349650

从上面代码可行,temporal实际上是Instant对象,Instant.getLong只支持四种字段类型。。

image-20210725200551164
image-20210725200551164

如果不是上面这几种字段类型,则抛出异常

DateUtil.format当遇到DateTimeFormatter会将Date对象首先转换为Instant,因为缺少时区,导致报错。

建议改法

先把date类型转化为LocalDateTime类型,然后再进行DateTimeFormatter.format(LocalDateTime)的格式化

测试demo

image-20210725201444728
image-20210725201444728

官方改法

修订版本 #5.7.5

更换了新的调用方法TemporalAccessorUtil.format(date.toInstant(), format),date.toInstant()返回Instant对象,则变成了TemporalAccessorUtil.format(Instant, format)

对比了下跟5.6.5版本的差异,新增了当time是Instant时,给一个默认的时区

image-2021072651290
image-2021072651290

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

方法描述

格式化日期时间<br> 格式 yyyy-MM-dd HH:mm:ss

源码分析一

首先好习惯,先对入参进行判空处理

然后调用DatePattern.NORM_DATETIME_FORMAT.format(date)返回FastDateFormat对象

针对只支持java8之前的程序,可以使用FastDateFormat线程安全替换SimpleDateFormat线程不安全–》源码分析

则转化为了FastDateFormat.format(date)

先把date转化为Calendar,方便获取日期和时间

核心的代码是这块

测试demo

断点跟进代码:

image-20210725211322291
image-20210725211322291

往下跟代码

image-20210725203801875
image-20210725203801875

已经取到年份了:2017

image-20210725204215108
image-20210725204215108

往下跟代码:

image-20210725211459199
image-20210725211459199

就是把’-‘字符串直接拼接上去。

下一个获取月份:

image-20210725211534912
image-20210725211534912

获取了月份:3

image-20210725205900990
image-20210725205900990

然后下一个:把’-‘字符串直接拼接上去。

image-20210725211609400
image-20210725211609400

继续往下跟

image-20210725211704501
image-20210725211704501
image-20210725210353207
image-20210725210353207

这样获取到的日期:2017-03-01

然后加了一个空格字符串

image-20210725211811625
image-20210725211811625

时分秒的调用,都是调用一样的FastDatePrinter#TwoDigitNumberField。

image-20210725212005035
image-20210725212005035

这样就得到了”2017-03-01 00:00:00″

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

方法描述

格式化日期部分(不包括时间)<br> 格式 yyyy-MM-dd

源码分析一

首先好习惯,先对入参进行判空处理

然后调用DatePattern.NORM_DATE_FORMAT.format(date)返回FastDateFormat对象

针对只支持java8之前的程序,可以使用FastDateFormat线程安全替换SimpleDateFormat线程不安全–》源码分析

则转化为了FastDateFormat.format(date),源码分析看上面

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

方法描述

格式化时间<br> 格式 HH:mm:ss

源码分析一

首先好习惯,先对入参进行判空处理

然后调用DatePattern.NORM_TIME_FORMAT.format(date)返回FastDateFormat对象

针对只支持java8之前的程序,可以使用FastDateFormat线程安全替换SimpleDateFormat线程不安全–》源码分析

则转化为了FastDateFormat.format(date),源码分析看上面

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

方法描述

格式化为Http的标准日期格式<br> 标准日期格式遵循RFC 1123规范,格式类似于:Fri, 31 Dec 1999 23:59:59 GMT

源码分析一

首先好习惯,先对入参进行判空处理

然后调用DatePattern.HTTP_DATETIME_FORMAT.format(date)返回FastDateFormat对象

针对只支持java8之前的程序,可以使用FastDateFormat线程安全替换SimpleDateFormat线程不安全–》源码分析

则转化为了FastDateFormat.format(date),源码分析看上面

方法名称:DateUtil.formatChineseDate(java.util.Date, boolean, boolean)

方法描述

格式化为中文日期格式,如果isUppercase为false,则返回类似:2018年10月24日,否则返回二〇一八年十月二十四日

源码分析一

首先好习惯,先对入参进行判空处理

当不采用大写形式时

执行**(withTime ? DatePattern.CHINESE_DATE_TIME_FORMAT : DatePattern.CHINESE_DATE_FORMAT).format(date)**

这里用了一个多目运算,包含时间部分时,调用DatePattern.CHINESE_DATE_TIME_FORMAT .format(date), 不包含时间部分时,调用DatePattern.CHINESE_DATE_FORMAT.format(date)

由上面源码可知,两个都是返回FastDateFormat对象。

针对只支持java8之前的程序,可以使用FastDateFormat线程安全替换SimpleDateFormat线程不安全–》源码分析

则转化为了FastDateFormat.format(date),源码分析看上面

当采用大写形式时

执行CalendarUtil.formatChineseDate(CalendarUtil.calendar(date), withTime);

可以拆解成两部分:

CalendarUtil.calendar(date)源码分析:

如果是hutool提供的DateTime类型,可以直接转化获取。

如果是date类型,则通过*cal.setTimeInMillis转化为Calendar对象。

有同学会发现,这个跟我们常用的Calendar.setTime(Date date),不一样,看了下源码

本质上是一样的。。setTime方法里也是会调用setTimeInMillis方法。

CalendarUtil.formatChineseDate(Calendar calendar, boolean withTime)源码分析:

由源码可知,是按年月日时分秒,每个字段进行转化。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/129006.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年4月1,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 源码分析目的
  • 项目引用
  • 方法名称:DateUtil.formatLocalDateTime(java.time.LocalDateTime)
    • 方法描述
      • 源码分析一
      • 方法名称:DateUtil.format(java.time.LocalDateTime, java.lang.String)
        • 方法描述
          • 源码分析一
          • 方法名称:DateUtil.format(java.util.Date, java.text.DateFormat)
            • 方法描述
              • 源码分析一
              • 方法名称:DateUtil.format(java.util.Date, java.time.format.DateTimeFormatter)(方法有问题,已反馈,官方已修正)
                • 方法描述
                  • 源码分析一
                    • 建议改法
                      • 官方改法
                      • 方法名称:DateUtil.formatDateTime(java.util.Date)
                        • 方法描述
                          • 源码分析一
                          • 方法名称:DateUtil.formatDate(java.util.Date)
                            • 方法描述
                              • 源码分析一
                              • 方法名称:DateUtil.formatTime(java.util.Date)
                                • 方法描述
                                  • 源码分析一
                                  • 方法名称:DateUtil.formatHttpDate(java.util.Date)
                                    • 方法描述
                                      • 源码分析一
                                      • 方法名称:DateUtil.formatChineseDate(java.util.Date, boolean, boolean)
                                        • 方法描述
                                          • 源码分析一
                                            • 当不采用大写形式时
                                            • 当采用大写形式时
                                        相关产品与服务
                                        腾讯云代码分析
                                        腾讯云代码分析(内部代号CodeDog)是集众多代码分析工具的云原生、分布式、高性能的代码综合分析跟踪管理平台,其主要功能是持续跟踪分析代码,观测项目代码质量,支撑团队传承代码文化。
                                        领券
                                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档