当前位置: 首页 > 后端技术 > Java

SpringBoot时间格式化的5种方法!

时间:2023-04-01 23:46:29 Java

在我们的日常工作中,时间格式化是很常见的事情,那么本文就来盘点一下SpringBoot中时间格式化的几种方法。时间问题演示为了方便演示,我写了一个简单的SpringBoot工程,在数据库中包含一个userinfo表。其组成结构和数据信息如下:项目目录如下:UserController实现代码如下:@RestController@RequestMapping("/user")publicclassUserController{@ResourceprivateUserMapperuserMapper;@RequestMapping("/list")publicListgetList(){returnuserMapper.getList();}}UserMapper实现代码如下:@MapperpublicinterfaceUserMapper{publicListgetList();}UserInfo实现代码如下:@DatapublicclassUserInfo{privateintid;私有字符串用户名;私人日期创建时间;privateDateupdatetime;}UserMapper.xml实现代码如下:select*fromuserinfo通过写完以上内容,我们就创建了一个简单的SpringBoot项目。接下来我们使用PostMan模拟调用UserController接口。执行结果如下:从上面的结果可以看出时间字段createtime和updatetime的显示方式很“乱”,不符合我们的阅读习惯,也不能直接显示给前端用户.这时候,我们就需要对时间进行格式化。时间格式化方法一共包括以下5种方法。1.前端时间格式化如果后端在公司有绝对的话语权,或者后端实力比较强,我们可以强行把时间格式化这“锅”扔给前端处理。为了让这个“锅”摇得更顺畅(可惜雷哥不当厨师),我们可以给前端工程师提供一个可行的时间格式化方法,实现代码如下。JS版本时间格式化函数dateFormat(fmt,date){letret;constopt={"Y+":date.getFullYear().toString(),//年"m+":(date.getMonth()+1).toString(),//月"d+":日期。getDate().toString(),//日“H+”:date.getHours().toString(),//小时“M+”:date.getMinutes().toString(),//分“S+”:日期.getSeconds().toString()//秒数//可以添加其他格式化字符,必须转成字符串};for(letkinopt){ret=newRegExp("("+k+")").exec(fmt);if(ret){fmt=fmt.replace(ret[1],(ret[1].length==1)?(opt[k]):(opt[k].padStart(ret[1].length,“0”)))};};returnfmt;}方法调用:letdate=newDate();dateFormat("YYYY-mm-ddHH:MM:SS",date);>>>2021-07-2521:45:122.SimpleDateFormat格式化在大多数情况下,我们仍然需要靠自己的努力来清理积雪。这个时候我们的后端程序员就需要发挥自己的特长了。我们提供的第一个时间格式化方法是使用SimpleDateFormat进行时间格式化。也是JDK8之前重要的时间格式化方法,其核心实现代码如下://定义时间格式化对象,定义格式化样式SimpleDateFormatdateFormat=newSimpleDateFormat("yyyy-MM-ddHH:mm:ss");//格式化时间对象Stringdate=dateFormat.format(newDate())接下来我们在这个项目中使用SimpleDateFormat来实现时间格式化,其实现代码如下:@RequestMapping("/list")publicListgetList(){//定义时间格式化对象SimpleDateFormatdateFormat=newSimpleDateFormat("yyyy-MM-ddHH:mm:ss");Listlist=userMapper.getList();//循环执行时间格式化list.forEach(item->{//使用保留字段ctime接收createtime的格式化时间(Date->String)item.setCtime(dateFormat.format(item.getCreatetime()));item.setUtime(dateFormat.format(item.getUpdatetime()));});returnlist;}程序执行结果如下:从上面的结果可以看出,时间格式化没有问题,达到了我们的预期目的,但是细心的读者会发现为什么接口的return字段已经改变?(之前的字段是createtime,现在是ctime。。。)这是因为使用了#SimpleDateFormat.format方法后,返回的是String类型的结果,而我们之前的createtime和updatetime字段都是Date类型,所以无法接收时间格式的结果。所以这时候我们需要在实体类UserInfo中添加两个字符串类型的“时间”字段,然后隐藏之前的数据类型的时间字段。实体类UserInfo最终的实现代码如下:私有字符串用户名;@JsonIgnore//输出结果时隐藏该字段privateDatecreatetime;//时间格式化后字段privateStringctime;@JsonIgnore//输出结果时隐藏该字段privateDateupdatetime;//时间格式化后的字段privateStringutime;}我们可以使用@JsonIgnore注解隐藏该字段,隐藏后的执行结果如下:3.DateTimeFormatter格式化JDK8后,我们可以使用DateTimeFormatter代替SimpleDateFormat,因为SimpleDateFormat不是线程安全的,而DateTimeFormatter是线程安全的,所以如果是JDK8以上的项目,尽量使用DateTimeFormatter进行时间格式化。DateTimeFormatter格式化代码与SimpleDateFormat类似,具体实现如下:@RequestMapping("/list")publicListgetList(){//定义时间格式化对象DateTimeFormatterdateFormat=DateTimeFormatter.ofPattern("yyyy-MM-ddHH:mm:ss");Listlist=userMapper.getList();//循环执行时间格式list.forEach(item->{//使用保留字段ctime接收createtime(Date->String)格式化的时间item.setCtime(dateFormat.format(item.getCreatetime()));item.setUtime(dateFormat.format(item.getUpdatetime()));});returnlist;}执行结果如下:DateTimeFormatter和SimpleDateFormat的区别在于DateTimeFormatter是用来格式化JDK8提供的时间类型,比如LocalDateTime,而SimpleDateFormat是用来格式化Date类型的,所以我们需要制作对UserInfoer实体类进行如下修改:私有字符串用户名;@JsonIgnoreprivateLocalDateTime创建时间;私有字符串ctime;@JsonIgnore私有LocalDateTime更新时间;privateStringutime;}我们可以使用LocalDateTime来接收MySQL4中的datetime类型。全局时间格式化上面两种后端格式化的实现都有一个致命的缺点,它们在时间格式升级的时候,需要对核心业务类进行一定的修改。这相当于为了解决一个问题引入了一个新问题。有没有更简单优雅的解决方案?答案是:是的。我们不需要改动任何代码,只需要在配置文件中设置即可实现时间格式化功能。首先,我们找到SpringBoot的配置文件application.properties(或application.yml)。我们只需要在application.properties配置文件中加入如下两行配置即可:#格式化全局时间字段spring.jackson.date-format=yyyy-MM-ddHH:mm:ss#指定时区类型spring.jackson.time-zone=GMT+8这样设置后,我们就恢复原来的UserInfo和UserController。UserInfo实现代码如下:importlombok.Data;importjava.util.Date;@DatapublicclassUserInfo{privateintid;私有字符串用户名;私人日期创建时间;privateDateupdatetime;}UserController实现代码:@RequestMapping("/list")publicListgetList(){returnuserMapper.getList();}然后我们运行程序,看到的执行结果如下:从上面的结果和代码可以看出,我们只需要在程序中简单配置一下,就可以实现所有时间字段的格式化。实现原理分析为什么所有时间字段的格式化都可以通过在配置文件中设置来实现?#格式化全局时间字段spring.jackson.date-format=yyyy-MM-ddHH:mm:ss#指定时区类型spring.jackson.time-zone=GMT+8这是因为Controller返回数据时,它会自动调用SpringBoot框架中内置的JSON框架Jackson,对返回的数据进行统一的JSON格式化处理。处理过程中会判断配置文件中是否设置了“spring.jackson.date-format=yyyy-MM-ddHH:mm:ss”,如果设置了,那么Jackson框架在输出时间的时候会进行时间格式化-type字段,这样我们就可以通过配置实现全局时间字段的格式化功能。为什么要指定时区类型“spring.jackson.time-zone=GMT+8”?最现实的原因是,如果我们不指定时区类型,查询时间会比预期时间少8小时,因为我们(中国)所在的时区比世界时间少8小时。是的,而且当我们设置了时区后,我们的时间查询就会和预期的时间保持一致。什么是格林威治标准时间?“GMT”在时区设置中是什么意思?GreenwichMeanTime(GMT)格林威治标准时间,又称世界时间。格林威治标准时间格林威治标准时间是前英国伦敦南郊皇家格林威治天文台的所在地,是地球本初子午线的标示地,也是世界计算时间和经度的起点。以其航海历史而闻名,作为本初子午线的标准点,格林威治标准时间就是以此命名的。这里地势险要,风景优美,既有历史,又有风土人情。它也是泰晤士河畔伦敦的东部门户。格林威治标准时间不仅被天文学家使用,也经常出现在新闻和报纸上。我们知道到处都有当地时间。如果使用当地时间来记录世界上的重要事件,将会变得复杂和不便。而且以后很容易出错。因此,天文学家提出了一种方便且为大家所接受的记录方式,那就是以格林威治标准当地时间为标准。从本初子午线午夜算起的平均太阳时。也称为格林威治标准时间或格林威治标准时间。正常时间和世界标准时间之间的差异等于该地点的地理经度。它在1960年之前被广泛用作基本时间测量系统。由于地球自转速度一度被认为是匀速的,所以1960年以前世界时被认为是匀速时间。由于地球自转速度变化的影响,不是匀速时间系统,与原子时没有理论关系或机械时间,它们只能通过观察来比较。后来世界时先后被历书时和原子时所取代,但在日常生活、天文导航、大地测量和航天飞行中仍然是必需的;同时,世界时反映了地球自转速率的变化,是地球自转参数之一。仍然是天文学和地球物理学的基础数据。5.部分时间格式化在某些场景下,我们不需要对全局时间进行统一处理。这种情况下,我们可以使用注解来实现部分时间字段的格式化。我们需要在实体类UserInfo上添加@JsonFormat注解,这样才能实现时间格式化功能。实现代码如下:私有字符串用户名;//格式化创建时间字段@JsonFormat(pattern="yyyy-MM-ddhh:mm:ss",timezone="GMT+8")privateDatecreatetime;privateDateupdatetime;}修改代码后,我们运行项目,执行结果如下:从上面的结果可以看出,时间的格式也可以通过注解来实现。它的实现原理和第四种时间格式的实现原理类似,都是在返回数据前对相应的字段进行时间格式处理。总结在本文中,我们介绍了时间格式化的五种实现方式,第一种是前端时间格式化方式,后四种是后端格式化方式。SimpleDateFormat和DateTimeFormatter格式化方法更适合普通的Java项目,其中SimpleDateFormat不是线程安全的,而DateTimeFormatter是线程安全的,但都不是SpringBoot项目中最优的时间格式化方案。如果是SpringBoot项目,建议使用第四种全局时间格式或者第五种本地时间格式方式。这两种实现方式不需要修改核心业务代码,通过简单的配置即可完成增加了时间格式化功能。Reference&Acknowledgmentswww.jianshu.com/p/49fb78bca621baike.baidu.com/item/WorldTime/692237关注公众号“Java中文社区”,查看更多有趣、知识性的SpringBoot文章。