一篇文章解决 Java 中的时间,时区问题

java中的时间存储到数据库

数据中的时间一般有 datetime 和 timestamp 两种类型

使用 datetime 存储数据的时间精度在秒,使用时间戳的精度在毫秒,也就是 0.001 秒

java.util.data java.sql.data 的区别

https://stackoverflow.com/questions/2305973/java-util-date-vs-java-sql-date

这两种存储方式本身都没有什么优劣,但是有些同学可能在使用数据库存储 datetime 类型存储的时候发现数据库的时间总是比时间早了八个小时,这是由于时区的问题所导致的。

数据库连接上不设置时区,那么数据在存储为 datetime 类型的时候就会默认存储utc标准时区的的时间,而我们中国是在东八区,所以直接去数据库看就会早了八个小时

所以在我们在 properties 文件中配置数据库的连接的时候,就可以按照如下的方式设置:

关键部分为 &serverTimezone=GMT%2B8,这条属性告诉数据库,我们目前的时区是哪个,方便各种 orm 框架在存储或者是读取时间时,选择合适的时区处理

1
2
3
4
5
# 数据库配置
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test_mybatis?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=password

java 中的时间进行序列化

把时间之类的序列化为 json 格式

序列化的时候如何序列化

java 中我们一般用 java.util.Date 来存储时间。可是大家都知道时间

spring boot 或者 spring mvc 中用的序列化工具是 jackson。jackson 序列化对象时使用注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package me.liluyang.jpa.entity;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.*;
import java.util.Date;
import java.util.List;

/**
* 实体类Demo
*/
@Data
@Table
@Entity
@NoArgsConstructor
@AllArgsConstructor
public class User {

@Id
private String id;

private String username;

private String password;

private String gender;

private Date lastLoginAt;

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateAt;

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createAt;

@OneToOne
private Address address;

@JsonIgnoreProperties("users")
@ManyToMany(mappedBy = "users")
private List<Role> roles;

public User(String id, String username) {
this.id = id;
this.username = username;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
// junit 测试代码
@Test
public void testInsert() throws Exception {
User user = new User();
user.setUsername("john");
user.setLastLoginAt(new Date());
user.setUpdateAt(new Date());
user.setCreateAt(new Date());

// 三个输出分别是:"lastLoginAt":1564208521736,"updateAt":"2019-07-27 06:22:01","createAt":"2019-07-27 14:22:01"
// 如果我们要格式化输出时间的话一定要指定合适的时区
log.info("date:" + new ObjectMapper().writeValueAsString(user));
}

通过使用不同的 jackson 注解,我们发现返回给前台的时间类型格式也不一样。如果不设定时区,前端获取的时间就会有误,这是不可以的,而且如果不设置 jsonformat 时间会以时间戳的格式传递,这样对代码读起来不是很友好,所以最好是使用格式化时间加时间戳的方式去保存

参考链接

~


面条先生 wechat
欢迎关注我的 “知乎日报” 小程序