在一个项目中,经常会用到关于时间和日期的记录,比如创建时间,修改时间,开始时间,结束时间等。而在写项目过程中,前后端传输关于时间的数据时,经常因为格式的问题导致获取和显式的时间日期不合理,遇到具体问题需要具体的分析。但有一部分情况其实都是细节问题引起的,解决起来很简单,注意细节很重要。
数据库时间类型
简单了解以下,数据库存储时间时常用的类型有:
Date类型:用来存储没有时间的日期格式"YYYY-MM-DD",范围在"1000-00-00"到"9999-12-31"。
Datetime类型:存储日期加时间的格式"YYYY-MM-DD HH:MM:SS",范围在"1000-00-00 00:00:00"到"9999-12-31 23:59:59"。
Timestamp类型,存储和显式的格式跟Datetime一样,只是范围不同,Timestamp范围在"1970-01-01 00:00:01"到"2038-01-19 03:14:07"。
数据库时间类型定义好之后,到后端实体类中定义时间变量,最常见的时间数据类型就是Date,也有很多人为了方便存储和显示,选择直接用String类型表示时间也是可以的。到了最关键的地方就是将数据传给前端,由前端展示出时间。
常见的显示时间问题
情况一、无时间显示
第一种常见的情况就是没有显示任何时间
这种情况其实很有可能是前端展示的字段和后端传递数据的字段没有对应上,例如
实体类定义的字段名称
前端获取的字段名称
注意这两个字段名称必须完全相同,一个字母的错误、一个大小写的错误都会导致获取不到数据,注意细节。
具体的字段名称,都会与实体类字段相互对应,如果不清楚前端获取的数据是怎样的字段,可以通过debug断点和浏览器后台查看请求获取的具体数据信息来确定。
情况二、时间格式不符
第二种常见问题,页面只显示年月日或者其他特殊格式,并不是我们实际想展示的年月日加上时间("YYYY-MM-DD HH:MM:SS")格式的数据。
第一,先确认数据库中定义的时间字段的时间类型是否符合要求,如果不符合及时修改成符合要求的时间类型。
第二,如果数据库类型正确,那么就要查看后端从数据库中查询到的时间数据,此时后端实体类中定义的字段如果是Date类型,那么传递给前端的时间,很可能就是这样的
面对时间的格式问题
方法一:可以在实体类上加上注解@JsonFormat或者@DateTimeFormat这种时间格式化注解,使用此注解前需要先引入Maven依赖
<!-- @JsonFormat依赖 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>对应版本</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>对应版本</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>对应版本</version>
</dependency>
<!-- @DateTimeFormat依赖 -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>对应版本</version>
</dependency>
导入依赖后在实体类中使用该注解在表示时间的字段上
/**
* @JsonFormat参数:
* pattern:表示日期的格式
* timezone:默认是GMT
*/
@JsonFormat(pattern= "yyyy-MM-dd HH:mm:ss", timezone= "GMT+8")
private Date createDate;
/**
* @DateTimeFormat参数:
* pattern:表示日期的格式
*/
@DateTimeFormat(pattern= "yyyy-MM-dd HH:mm:ss")
private Date createDate;
此时该时间字段的格式就是我们定义的"yyyy-MM-dd HH:mm:ss"格式了。要注意的一点是在什么地方用"-",什么地方用":"一定要注意,这里很容易写错,并且很容易忽略掉这里。
除了注解以外还有一种常用的解决办法
方法二:就是SimpleDateFormat类,它可以通过函数语法自定义想要返回的格式或形式。只要掌握不同主要字符的含义就可以灵活应用。
yyyy: 年份
MM: 月份
dd: 日/号
hh: 时(12时制,1~12时)
HH: 时(24时制,1~24时)
mm: 分钟
ss: 秒钟
S: 毫秒
E: 星期几(星期1~7)
D: 一年中的第几天
F: 一个月中的第几个星期的星期几(用日期/7计算)
w: 一年中的第几个星期
W: 一个月中的第几个星期
a: 区别上下午(AM/PM)
k: 一天中的某个小时(24时制,1~24时)
K: 一天中的上午或下午的某个小时(12时制,1~12时)
z: 表示时区
具体实现方式,因为该方法可以作用在很多情况下,所以将代码提取出写成工具类,能使项目中更多的类更方便的使用其方法。
public class TimeUtil{
//返回字符串形式的
public String getTime(){
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//自定义时间格式
String time = sdf.format(date);//将时间格式转换成"yyyy-MM-dd HH:mm:ss"形式的字符串
return time;
}
//返回时间形式的
public Date getNewTime(){
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//自定义时间格式
String formatTime = sdf.format(date);//将时间格式转换成"yyyy-MM-dd HH:mm:ss"形式的字符串
Date parseTime = sdf.parse(formatTime);//将字符串变成Date类型的时间
return parseTime;
}
}
情况三、前端显示问题
第三种情况,后端传递给前端的数据格式符合要求,可是前端展示时不符合要求,或者后端传递完整的年月日时间,但个别情况下前端只需要年月日,此时如果直接修改后端影响其他情况的使用,针对个别页面的时间显示该怎么办呢?
前端解决方式是在前端也定义要展示的时间格式,例如
<!-- 后端传递"yyyy-MM-dd HH-mm-ss"格式,此时只展示年月日"yyyy-MM-dd"格式时,代码修改如下 -->
<el-table-column label="显示时间" prop="createDate">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createDate, '{y}-{m}-{d}')}}</span>
</template>
</el-table-column>
这样前端展示的效果就是只有年月日
修改前
修改后
这里只是一些平时常常遇到又很容易忽略的小问题和一些比较容易解决的方法。在实际项目中关于时间的问题远不止这些,还有很多更优秀更精彩更值得学习的解决办法和方式。就留在以后慢慢学习吧,追求进步,学无止境。