springboot:时间格式化的5种方法(解决后端传给前端的时间格式转换问题)推荐使用第4和第5种!

本文转载自:springboot:时间格式化的5种方法(解决后端传给前端的时间显示不一致)_为什么前端格式化日期了后端还要格式化_洛泞的博客-CSDN博客

时间问题演示

为了方便演示,我写了一个简单 Spring Boot 项目,其中数据库中包含了一张 userinfo 表,它
的组成结构和数据信息如下:

 项目目录是这样的:

 

UserController 实现代码如下: 

@RestController
@RequestMapping("/user")
publicclass UserController {
    @Resource
    private UserMapper userMapper;

    @RequestMapping("/list")
    public List<UserInfo> getList() {
        return userMapper.getList();
    }
}

UserMapper 实现代码如下:

@Mapper
public interface UserMapper {
    public List<UserInfo> getList();
}

UserInfo 实现代码如下:

@Data
publicclass UserInfo {
    privateint id;
    private String username;
    private Date createtime;
    private Date updatetime;
}

UserMapper.xml 实现代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper">
    <select id="getList" resultType="com.example.demo.model.UserInfo">
        select * from userinfo
    </select>
</mapper>

经过以上内容的编写,我们就制作出了一个简单的 Spring Boot 项目了。接下来,我们使用 PostMan 来模拟调用 UserController 接口,执行结果如下:

从上述结果可以看出,时间字段 createtime 和 updatetime 的显示方式是很“凌乱”的,并不符合我们的阅读习惯,也不能直接展示给前端的用户使用,这时候,我们就需要对时间进行格式化处理了。

时间格式化的方法总共包含以下 5 种。

1.前端时间格式化

JS 版时间格式化

假设您有一个名为`data`的数组,其中包含后端响应的数据,其中包含了`createdTime`字段

"createdTime": { "nano": 0, "year": 2021, "monthValue": 12, "dayOfMonth": 16, "hour": 5, "minute": 54, "second": 45, "dayOfWeek": "THURSDAY", "dayOfYear": 350, "month": "DECEMBER", "chronology": { "id": "ISO", "calendarType": "iso8601" } }

,您可以像这样在el-table中显示它: 

'''vue

<template>
  <div>
    <el-table :data="data">
      <el-table-column label="创建时间">
        <template slot-scope="scope">
          {{ formatDate(scope.row.createdTime) }}
        </template>
      </el-table-column>
      <!-- 其他列 -->
    </el-table>
  </div>
</template>
 
<script>
export default {
  data() {
    return {
      data: [], // 后端响应的数据
    };
  },
  methods: {
    formatDate(timestamp) {
      // 使用JavaScript的Date对象将时间戳格式化为某年-某月-某日 某时:某分:某秒
      const date = new Date(timestamp.year, timestamp.monthValue - 1, timestamp.dayOfMonth, timestamp.hour, timestamp.minute, timestamp.second);
      const year = date.getFullYear();
      const month = (date.getMonth() + 1).toString().padStart(2, '0'); // 补零
      const day = date.getDate().toString().padStart(2, '0');
      const hours = date.getHours().toString().padStart(2, '0');
      const minutes = date.getMinutes().toString().padStart(2, '0');
      const seconds = date.getSeconds().toString().padStart(2, '0');
      
      return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
    },
  },
};
</script>

'''

 2.SimpleDateFormat格式化(Date)

使用 SimpleDateFormat 来进行时间格式化,它也是 JDK 8 之前重要的时间格式化方法,它的核心实现代码如下:

// 定义时间格式化对象和定义格式化样式
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 格式化时间对象
String date = dateFormat.format(new Date())

 接下来我们使用 SimpleDateFormat 来实现一下本项目中的时间格式化,它的实现代码如下:

@RequestMapping("/list")
public List<UserInfo> getList() {
    // 定义时间格式化对象
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    List<UserInfo> list = userMapper.getList();
    // 循环执行时间格式化
    list.forEach(item -> {
        // 使用预留字段 ctime 接收 createtime 格式化的时间(Date->String)
        item.setCtime(dateFormat.format(item.getCreatetime()));
        item.setUtime(dateFormat.format(item.getUpdatetime()));
    });
    return list;
}

程序执行结果如下:

从上述结果可以看出,时间格式化没有任何问题,以及到底我们预想的目的了。但细心的读者会发现,为什么接口的返回字段咋变了呢?(之前的字段是 createtime 现在却是 ctime…)
这是因为使用 #SimpleDateFormat.format 方法之后,它返回的是一个 String 类型的结果,而我们之前的 createtime 和 updatetime 字段都是 Date 类型的,因此它们是不能接收时间格式化得结果的。
所以此时我们就需要在实体类 UserInfo 新增两个字符串类型的“时间”字段,再将之前 Data 类型的时间字段进行隐藏,最终实体类 UserInfo 的实现代码如下:

import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;

import java.util.Date;

@Data
publicclass UserInfo {
    privateint id;
    private String username;
    @JsonIgnore// 输出结果时隐藏此字段
    private Date createtime;
    // 时间格式化后的字段
    private String ctime;
    @JsonIgnore// 输出结果时隐藏此字段
    private Date updatetime;
    // 时间格式化后的字段
    private String utime;
}

我们可以使用 @JsonIgnore 注解将字段进行隐藏,隐藏之后的执行结果如下:

3.DateTimeFormatter格式化

JDK 8 之后,我们可以使用 DateTimeFormatter 来替代 SimpleDateFormat,因为 SimpleDateFormat 是非线程安全的,而 DateTimeFormatter 是线程安全的,所以如果是 JDK 8 以上的项目,尽量使用 DateTimeFormatter 来进行时间格式化。

DateTimeFormatter 格式化的代码和 SimpleDateFormat 类似,具体实现如下:

@RequestMapping("/list")
public List<UserInfo> getList() {
    // 定义时间格式化对象
    DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    List<UserInfo> list = userMapper.getList();
    // 循环执行时间格式化
    list.forEach(item -> {
        // 使用预留字段 ctime 接收 createtime 格式化的时间(Date->String)
        item.setCtime(dateFormat.format(item.getCreatetime()));
        item.setUtime(dateFormat.format(item.getUpdatetime()));
    });
    return list;
}

执行结果如下所示:

DateTimeFormatter 和 SimpleDateFormat 在使用上的区别是 DateTimeFormatter 是用来格式化 JDK 8 提供的时间类型的,如 LocalDateTime,而 SimpleDateFormat 是用来格式化 Date 类型的,所以我们需要对 UserInfoer 实体类做如下的修改:

import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import java.time.LocalDateTime;

@Data
publicclass UserInfo {
    privateint id;
    private String username;
    @JsonIgnore
    private LocalDateTime createtime;
    private String ctime;
    @JsonIgnore
    private LocalDateTime updatetime;
    private String utime;
}

我们可以使用 LocalDateTime 来接收 MySQL 中的 datetime 类型。

4.全局时间格式化

以上两种后端格式化的实现都有一个致命的缺点,它们在进行时间格式化的时候,都需要对核心业务类做一定的修改,这就相当为了解决一个问题,又引入了一个新的问题,那有没有简单一点、优雅一点的解决方案呢?

答案是:有的。我们可以不改任何代码,只需要在配置文件中设置一下就可以实现时间格式化的功能了。

首先,我们找到 Spring Boot 的配置文件 application.properties(或 application.yml),只需要在 application.properties 配置文件中添加以下两行配置:

'''properties

# 格式化全局时间字段
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
# 指定时间区域类型
spring.jackson.time-zone=GMT+8

'''

这样设置之后,我们将原始的 UserInfo 和 UserController 进行还原。

UserInfo 实现代码如下:

import lombok.Data;
import java.util.Date;

@Data
publicclass UserInfo {
    privateint id;
    private String username;
    private Date createtime;
    private Date updatetime;
}

UserController 实现代码:

@RequestMapping("/list")
public List<UserInfo> getList() {
    return userMapper.getList();
}

然后我们运行程序,看到的执行结果如下:

从以上结果和代码可以看出,我们只需要在程序中简单配置一下,就可以实现所有时间字段的格式化了。

实现原理分析
为什么在配置文件中设置一下,就可以实现所有时间字段的格式化了呢?

'''properties

# 格式化全局时间字段
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
# 指定时间区域类型
spring.jackson.time-zone=GMT+8

'''

这是因为 Controller 在返回数据时,会自动调用 Spring Boot 框架中内置的 JSON 框架 Jackson,对返回的数据进行统一的 JSON 格式化处理,在处理的过程中它会判断配置文件中是否设置了“spring.jackson.date-format=yyyy-MM-dd HH:mm:ss”,如果设置了,那么 Jackson 框架在对时间类型的字段输出时就会执行时间格式化的处理,这样我们就通过配置来实现全局时间字段的格式化功能了。

为什么要指定时间区域类型“spring.jackson.time-zone=GMT+8”呢?

最现实的原因是,如果我们不指定时间区域类型,那么查询出来的时间就会比预期的时间少 8 个小时,这因为我们(中国)所处的时间区域比世界时间少 8 个小时导致的,而当我们设置了时区之后,我们的时间查询才会和预期时间保持一致。

GMT 是什么?
时间区域设置中的“GMT” 是什么意思?

Greenwich Mean Time (GMT) 格林尼治时间,也叫做世界时间。

格林尼治时间
格林尼治是英国伦敦南郊原皇家格林尼治天文台所在地,地球本初子午线的标界处,世界计算时间和经度的起点。以其海事历史、作为本初子午线的标准点、以及格林尼治时间以其命名而闻名于世。这里地势险要,风景秀丽,兼具历史和地方风情,也是伦敦在泰晤士河的东方门户。

不光是天文学家使用格林尼治时间,就是在新闻报刊上也经常出现这个名词。我们知道各地都有各地的地方时间。如果对国际上某一重大事情,用地方时间来记录,就会感到复杂不便.而且将来日子一长容易搞错。因此,天文学家就提出一个大家都能接受且又方便的记录方法,那就是以格林尼治的地方时间为标准。

以本初子午线的平子夜起算的平太阳时。又称格林尼治平时或格林尼治时间。各地的地方平时与世界时之差等于该地的地理经度。1960年以前曾作为基本时间计量系统被广泛应用。由于地球自转速率曾被认为是均匀的,因此在1960年以前,世界时被认为是一种均匀时。由于地球自转速度变化的影响,它不是一种均匀的时间系统,它与原子时或力学时都没有任何理论上的关系,只有通过观测才能对它们进行比较。后来世界时先后被历书时和原子时所取代,但在日常生活、天文导航、大地测量和宇宙飞行等方面仍属必需;同时,世界时反映地球自转速率的变化,是地球自转参数之一,仍为天文学和地球物理学的基本资料。

5.部分时间格式化


某些场景下,我们不需要对全局的时间都进行统一的处理,这种情况我们可以使用注解的方式来实现部分时间字段的格式化。

我们需要在实体类 UserInfo 中添加 @JsonFormat 注解,这样就可以实现时间的格式化功能了,实现代码如下:

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;

@Data
publicclass UserInfo {
    privateint id;
    private String username;
    // 对 createtime 字段进行格式化处理
    @JsonFormat(pattern = "yyyy-MM-dd hh:mm:ss", timezone = "GMT+8")
    private Date createtime;
    private Date updatetime;
}

修改完代码之后,我们运行项目执行结果如下:

从上述结果可以看出,使用注解的方式也可以实现时间的格式化。它的实现原理和第 4 种时间格式化的实现原理类似,都是在返回数据之前,对相应的字段进行时间格式化的处理。

总结
本文我们介绍了 5 种时间格式化的实现方法,其中第 1 种为前端时间格式化的方法,后 4 种为后端格式化的方法,SimpleDateFormat 和 DateTimeFormatter 格式化的方法更适用普通的 Java 项目,其中 SimpleDateFormat 是非线程安全的,而 DateTimeFormatter 是线程安全的,但它们都不是 Spring Boot 项目中最优的时间格式化方案。

如果是 Spring Boot 的项目,推荐使用第 4 种全局时间格式化或第 5 种局部时间格式化的方式,这两种实现方式都无需修改核心业务代码,只需要简单的配置一下,就可以完成时间的格式化功能了。
————————————————
原文链接:https://blog.csdn.net/qq_41366629/article/details/118972757

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/100512.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot业务系统如何实现海量数据高效实时搜索

1.概述 我们都知道随着业务系统的发展和使用&#xff0c;数据库存储的业务数据量会越来越大&#xff0c;逐渐成为了业务系统的瓶颈。在阿里巴巴开发手册中也建议&#xff1a;单表行数超过500万行或者单表容量超过2GB才推荐进行分库分表&#xff0c;如果预计三年后数据量根本达…

微服务--服务介绍

Spring Cloud实现对比 Spring Cloud 作为一套标准&#xff0c;实现不一样 Spring Cloud AlibabaSpring Cloud NetflixSpring Cloud 官方Spring Cloud Zookeeper分布式配置Nacos ConficArchaiusSpring Cloud ConfigZookeeper服务注册/发现Nacos DiscoveryEureka--Zookeeper服务…

嵌入式学习笔记(7)ARM汇编指令4-多寄存器指令

多寄存器访问指令 ldr/str每周期只能访问4字节内存&#xff0c;如果需要批量读取、写入内存的话太慢&#xff0c;解决方案就是ldm/stm&#xff0c;ldm(load register multiple)&#xff0c;stm(store register multiple) 举例&#xff1a; stmia sp, {r0 - r12} 将r0存入sp指…

自动驾驶——【规划】记忆泊车特殊学习路径拟合

1.Back ground 如上图&#xff0c;SLAM学习路线Start到End路径&#xff0c;其中曲线SDAB为D档位学习路径&#xff0c;曲线BC为R学习路径&#xff0c;曲线AE为前进档D档学习路径。 为了使其使用记忆泊车时&#xff0c;其驾驶员体验感好&#xff0c;需去除R档倒车部分轨迹&#x…

画流程图都可以用哪些工具?

在日常生活中&#xff0c;我相信我们很多人都看到过流程图。对于设计师来说&#xff0c;它还需要涉及流程图来反映用户的旅程和交互方式。那么你知道哪些流行的流程图设计软件呢&#xff1f;作为高级设计师&#xff0c;我今天推荐10款流程图设计软件。你可以和我一起读这篇文章…

Aidex 移动端快速开发框架# RuoYi-Uniapp项目,uniapp vue app项目跨域问题

参考地址&#xff1a; manifest.json官方配置文档&#xff1a;manifest.json 应用配置 | uni-app官网 Chrome 调试跨域问题解决方案之插件篇&#xff1a; uni-app H5跨域问题解决方案&#xff08;CORS、Cross-Origin&#xff09; - DCloud问答 其实uni-app官方有解决跨域的办…

【C++心愿便利店】No.4---C++初谈类和对象

文章目录 前言一、面向过程和面向对象初步认识二、类的引用三、类的定义四、类的访问限定符及封装五、类的作用域六、类的实例化七、类对象模型八、this指针 前言 &#x1f467;个人主页&#xff1a;小沈YO. &#x1f61a;小编介绍&#xff1a;欢迎来到我的乱七八糟小星球&…

uniapp 配置并使用 VueX

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态&#xff0c;并以相应的规则保证状态以一种可预测的方式发生变化。 uni-app 内置了 VueX 1、创建需要的文件 右键点击 根目录【我的是 uni-shop】&#xff0c;然后新建 目录&a…

OBS Studio 30.0 承诺在 Linux 上支持英特尔 QSV,为 DeckLink 提供 HDR 回放功能

导读OBS Studio 30.0 现已推出公开测试版&#xff0c;承诺为这款广受欢迎的免费开源截屏和流媒体应用程序提供多项令人兴奋的新功能&#xff0c;以及大量其他更改和错误修复。 OBS Studio 30.0 承诺在 Linux 上支持英特尔 QSV&#xff08;快速同步视频&#xff09;、WHIP/WebRT…

对战ChatGPT,创邻科技的Graph+AI会更胜一筹吗?

大模型&#xff08;大规模语言模型&#xff0c;即Large Language Model&#xff09;的应用已经成为千行百业发展的必然。特定领域或行业中经过训练和优化的企业级垂直大模型则成为大模型走下神坛、真正深入场景的关键之路。 但是&#xff0c;企业级垂直大模型在正式落地应用前…

idea --Git Commit Template插件

Git Commit Template是一款免费的IntelliJ IDEA插件&#xff0c;用于提供Git提交模板。该插件可以帮助开发者编写规范的Git提交信息&#xff0c;提高代码管理效率。 首先安装插件&#xff1a; 使用Git Commit Template插件: 注&#xff1a;long description和Breaking changes…

新能源汽车动力总成系统及技术

需要动力系统总成的请联&#xff1a;shbinzer 拆车邦 需要动力系统总成的请联&#xff1a;shbinzer 拆车邦 需要动力系统总成的请联&#xff1a;shbinzer 拆车邦 需要动力系统总成的请联&#xff1a;shbinzer 拆车邦 需要动力系统总成的请联&#xff1a;shbinzer …

卸载Pycharm

1.运行 ‪‪D:\PyCharm 2019.3.3\bin\Uninstall.exe 2.删除相关注册表 删除 HKEY_CURRENT_USER\Environment\PyCharm 文件 删除 HKEY_CURRENT_USER\Software\JavaSoft\Prefs\jetbrains 文件夹 3.删除本地缓存 4.重启

博流RISC-V芯片Eclipse环境搭建

文章目录 1、下载 Eclipse2、导入 bouffalo_sdk3、编译4、烧录5、使用ninja编译 之前编译是通过 VSCode 编译&#xff0c;通过手工输入 make 命令编译&#xff0c;我们也可以通过 Eclipse 可视化 IDE 来编译、烧录。 1、下载 Eclipse 至 Eclipse 官网 https://www.eclipse.org…

下面是实践百度飞桨上面的pm2.5分类项目_logistic regression相关

part1:数据的引入&#xff0c;和前一个linear regression基本是一样 part2:数据解析——也就是数据的“规格化” 首先&#xff0c;打算用dataMat[]和labelMat[]数据存储feature和label&#xff0c;并且文件变量fr 然后&#xff0c;是这个for line in fr.readlines()循环&#…

kubernetes进阶 (一) 环境搭建

我是基于一台centos7.6的腾讯云主机进行操作的&#xff0c;配置为4C8G&#xff0c;之前的文档自己试着搭建发现有问题了&#xff0c;这里重新整理下笔记&#xff0c;集群版本选择1.22.2&#xff08;一年前搭的&#xff09;用的还不错 清理环境 之前我的环境可能装过docker或者什…

实现公网远程访问:Windows本地快速搭建SFTP文件服务器并配置端口映射

文章目录 1. 搭建SFTP服务器1.1 下载 freesshd服务器软件1.3 启动SFTP服务1.4 添加用户1.5 保存所有配置 2 安装SFTP客户端FileZilla测试2.1 配置一个本地SFTP站点2.2 内网连接测试成功 3 使用cpolar内网穿透3.1 创建SFTP隧道3.2 查看在线隧道列表 4. 使用SFTP客户端&#xff0…

最详细Maven下载、安装、配置教程

Maven是一个跨平台的项目管理工具。作为Apache组织的一个颇为成功的开源项目&#xff0c;其主要服务于基于Java平台的项目创建&#xff0c;依赖管理和项目信息管理。maven是Apache的顶级项目&#xff0c;解释为“专家&#xff0c;内行”&#xff0c;它是一个项目管理的工具&…

JVM调优指令参数

常用命令查找文档站点&#xff1a;https://docs.oracle.com/javase/8/docs/technotes/tools/unix/index.html -XX:PrintFlagsInitial 输出所有参数的名称和默认值&#xff0c;默认不包括Diagnostic和Experimental的参数。可以配合 -XX:UnlockDiagnosticVMOptions和-XX:UnlockEx…

【JavaEE】Spring事务-@Transactional参数介绍-事务的隔离级别以及传播机制

【JavaEE】Spring 事务&#xff08;2&#xff09; 文章目录 【JavaEE】Spring 事务&#xff08;2&#xff09;1. Transactional 参数介绍1.1 value 和 transactionManager1.2 timeout1.3 readOnly1.4 后面四个1.5 isolation 与 propagation 2. Spring 事务隔离级别 - isolation…