服务端时区问题

这是我参与8月更文挑战的第3天,活动详情查看:8月更文挑战mysql

关于时区,咱们先聊一下这样场景:程序员

咱们有一个商城系统,当用户在 2021-08-03 晚上8点时下了一笔单,这笔订单的下单时间能够记做 2021-08-03 20:00:00 或1627992000000(时间戳)。咱们并把这个时间储存到数据库,之后用户查询订单记录时,这笔订单的下单时间都为 2021-08-03 20:00:00sql

当咱们这个商城系统面向全球时,在上面所说的同一时刻,有一个美国用户在美国当地也下单了,那这个下单时间应该记为何呢?仍是 2021-08-03 20:00:00 吗?但众所周知,美国当地时间显然不是晚上8点,而是 2021-08-03 08:00:00(东部时间),若是用户在查询订单时,看到下单的时间是 2021-08-03 20:00:00,他必定会以为这是系统bug。数据库

那咱们有什么解决方法呢,最直接的方法就是增长两个下单时间字段:中国下单时间(下单时在中国属于什么时间),美国下单时间(下单时在美国属于什么时间)。这样咱们能够把中国下单时间和美国下单时间都记下来,美国用户查询订单时,就用美国下单时间。虽然这能暂时解决咱们的问题,可是若是真的这样设计,程序员必定会疯的,由于除了中国时间、美国时间,还有全球各地的时间。其实,最正确的处理方式就是给咱们的时间,增长时区概念。windows

时区:因为世界各国家与地区经度不一样,地方时也有所不一样,所以会划分为不一样的时区。为了照顾到各地区的使用方便,又使其余地方的人容易将本地的时间换算到别的地方时间上去,有关国际会议决定将地球表面按经线从东到西,划成一个个区域,而且规定相邻区域的时间相差1小时,现今全球共分为24个时区。服务器

回到上面的问题,下单时间2021-08-03 20:00:00,咱们把这个时间设定为北京时间(东八区),咱们能够根据时区对应关系,算出对应各地的时间,如此时美国东部时间为2021-08-03 08:00:00。markdown

MySQL时区相关问题

查看mysql当前时区
show variables like'%time_zone';
复制代码

查询结果(MySQL版本:5.5.20):oop

image.png

说明当前MySQL的时区根据系统时区决定。post

数据库时区变化

当咱们有以下数据:spa

// 表结构
CREATE TABLE `t_order` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
)
// 表数据
id      create_time`
1	2021-08-03 20:00:00
复制代码

修改系统时区,将北京时间改成美国东部时间(win1o系统可参考:如何更改 Windows 10 系统时区设置的 4 种简单方法),并重启MySQL服务器, 数据将会变为:

id      create_time`
1	2021-08-03 08:00:00
复制代码
数据库连接配置项serverTimezone

使用Mybatis查询数据库数据库时,咱们能够指定serverTimezone配置来控制日期对应的时区

一般的配置:

serverTimezone=GMT%2B8  // 时区为GMT+8,东八区时间,即北京时间。 说明:%2B为「+」的URL转码
serverTimezone=Asia/Shanghai // 上海时区,也为北京时间。 
复制代码

若是须要修改时区,只须要修改配置,如serverTimezone=GMT%2B9东九区时间;serverTimezone=America/Chicago美国芝加哥时间。城市可参考:全球地区时区代码

LocalDateTime 和 Date

Java的LocalDateTime和Date类均可以表示时间,但它们仍是有区别的。其中一个区别就是时区:

LocalDateTime 本地时间,当咱们查询数据库时间数据时,无论serverTimezone配置成哪一个时区,若是咱们LocalDateTime接收数据,时间都是同样的。

Date 时间,当咱们查询数据库时间数据时,Date接收的时间会根据serverTimezone配置的时区而变化。

Java根据时区格式化时间

用法:

Long t = 1627992000000L;

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 指定时区
df.setTimeZone(TimeZone.getTimeZone("GMT+8"));
System.out.println(df.format(t));


SimpleDateFormat df1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 指定时区
df1.setTimeZone(TimeZone.getTimeZone("GMT+7"));
System.out.println(df1.format(t));

SimpleDateFormat df2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 使用系统默认时区,可经过TimeZone.setDefault()方法修改系统默认时区(全局生效)
System.out.println(df2.format(t));

// 输出结果:
2021-08-03 20:00:00
2021-08-03 19:00:00
2021-08-03 20:00:00
复制代码
相关文章
相关标签/搜索