统一javaweb项目和mysql数据库时间UTC时间方法及原理

文章目录

    • 统一javaweb项目和mysql数据库时间UTC时间方法及原理
  • 前言
    • UTC时间与 GMT时间
    • 时间戳和时区
  • mysql时间字段解读
    • 4种日期类型
    • 比如datetime和timestamp区别
    • 查看和修改时区
  • java里时间类
    • 获得系统时间类
    • 获得UTC时间
  • mysql获得当前时间的特有关键字
  • mysql时间类型和java时间类对应关系
  • mybatis处理java时间类和mysql时间类型方式
  • JDBC连接数据库设置时区
  • 总结
    • mysql数据库里
    • javaweb
      • 直接写sql情况下
      • 使用javabean传递时间
    • 其它

前言

由于在时间处理上,北京时间和世界时间相差8小时,如果时间处理不当,会造成程序混乱。所以必需统一时间,建议使用UTC时间,当然使用北京时间也没毛病。

UTC时间与 GMT时间

  1. UTC:协调世界时,又称世界统一时间,世界标准时间,国际协调时间,简称UTC。
  2. GMT:经过格林威治老天文台本初子午线的时间便被称为世界时,定义为从格林威治时间1970年01月01日00时00分00秒起至现在的总秒数。
    我们可以认为格林威治时间就是时间协调时间(GMT=UTC),格林威治时间和UTC时间均用秒数来计算的。

本地时间=UTC + 时区差
例如:
北京时间:2019-03-22 12:20:00
UTC时间:2019-03-22 12:20:00 UTC+8:00
GMT时间:2019-03-22 4:20:00 UTC+0:00

时间戳和时区

  1. 时间戳:
    所有的linux系统文件系统底层存储的都是UTC时间,也就是说都是自1970年0时0分0秒以来的UTC标准时间的秒数。
    无论系统配置是什么时区,显示如何不同,底层存储都是一致的,这个时间叫时间戳。
    时间戳不分东西南北、在地球的每一个角落都是相同的。
  2. 时区:
    时间戳在地球的每一个角落都是相同的,但是在相同的时间点会有不同的表达方式,所以有了另外一个时间概念,叫时区。例如北京时间叫东八区

mysql时间字段解读

4种日期类型

参考官方文档
mysql中有4种日期类型

  1. date
    只有年月日,没有时分秒,格式如下:YYYY-MM-DD
    支持时间范围是1000-01-01’ to '9999-12-31
    很少用
  2. time
    只有时分秒,格式如下: HH:MM:SS
    很少用
  3. datetime
    年月日时分秒,格式如下:YYYY-MM-DD HH:MM:SS
    支持时间范围是1000-01-01’ to '9999-12-31
  4. timestamp
    时间戳,常用,返回的格式是YYYY-MM-DD HH:MM:SS。如果想获得数字值(UTC时间),在列后台添加+0
    比如

select now();
结果
+---------------------+
| now()               |
+---------------------+
| 2019-03-22 10:21:50 |
+---------------------+
1 row in setselect now()+0;
结果
mysql> select now()+0;
+----------------+
| now()+0        |
+----------------+
| 20190322102206 |
+----------------+
1 row in set

比如datetime和timestamp区别

  1. 两者的存储方式不一样
    对于TIMESTAMP,它把客户端插入的时间从当前时区转化为UTC(世界标准时间)进行存储(换句话说,将当前时区时间转化成自1970年0时0分0秒以来的UTC标准时间的秒数)。查询时,将其又转化为客户端当前时区进行返回。而对于DATETIME,不做任何改变,基本上是原样输入和输出。

sql语句当前时区时间,不能插入UTC时间(比如2019-03-22T02:00:00Z)。这个区别对开发者和用户是透明的,可以忽略

  1. 两者所能存储的时间范围不一样
    timestamp所能存储的时间范围为:’1970-01-01 00:00:01.000000’ 到 ‘2038-01-19 03:14:07.999999’。
    datetime所能存储的时间范围为:’1000-01-01 00:00:00.000000’ 到 ‘9999-12-31 23:59:59.999999’。

没太大区别,可以忽略这个区别

  1. 自动初始化和更新
    自动初始化指的是如果对该字段(譬如上例中的hiredate字段)没有显性赋值,则自动设置为当前系统时间。
    自动更新指的是如果修改了其它字段,则该字段的值将自动更新为当前系统时间。

timestamp有自动初始化和更新,当你update某条记录的时候,该列值会自动更新,这是和datatime最大的区别。
其实2者区别不是特别的大,但timestamp比datetime常用。

查看和修改时区

查看时区

show variables like "%time_zone%";
返回
mysql> show variables like "%time_zone%";
+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone |        |
| time_zone        | SYSTEM |
+------------------+--------+
2 rows in set

说明time_zone和system_time_zone使用system的时区,而在中国,时区基本上都是东八区,在linux上查看时区date -R

java里时间类

获得系统时间类

参考java8 LocalDate LocalDateTime等时间类介绍
下面的方法是获得当前时区时间

  1. LocalDate:LocalDate只提供日期不提供时间信息。它是不可变类且线程安全的。
    获得当前日期:LocalDate.now();
  2. LocalTime:LocalTime只提供时间而不提供日期信息,它是不可变类且线程安全的。
    获得当前时间:LocalTime.now();
  3. LocalDateTime:LocalDateTime提供时间和日期的信息,它是不可变类且线程安全的
    获得当前日期和时间:LocalDateTime.now();
  4. Year:Year提供年的信息,它是不可变类且线程安全的。
  5. Duration:Duration是用来计算两个给定的日期之间包含多少秒,多少毫秒,它是不可变类且线程安全的
  6. Period: Period是用来计算两个给定的日期之间包含多少天,多少月或者多少年,它是不可变类且线程安全的
LocalDate localDate = LocalDate.now();Period period = Period.between(localDate, localDate.plus(2, ChronoUnit.DAYS));System.out.println(period.getDays());

获得UTC时间

使用Instant,这个类只有获得UTC时间。

//获得当前时间
Instant instant = Instant.now();
// 以ISO-8601输出
System.out.println(instant);
//结果:
2019-03-20T16:22:52.966Z//解析时间
从字符串类型中创建Instant类型的时间
instant = Instant.parse("2019-03-20T16:22:52.966Z");

mysql获得当前时间的特有关键字

CURRENT_TIMESTAMP:获得当前时区时间,
UTC_TIMESTAMP:获得当前UTC时间
如果对时间不统一,会造成数据库里时间有的是UTC时间,有的是当前时区的时间。
在javaweb开发时我们经常遇到
Tomcat java使用UTC时区进行处理业务逻辑。从而导致Mysql数据库中lastModifyTime值查询后转到Java Bean,值少了8个小时。
修改方法有很多种

  1. 保持两个系统的时区一致;由于Tomcat使用UTC时间,可以在Mysql中使用UTC_TIMESTAMP,而不是CURRENT_TIMESTAMP,这样时区就都是UTC了。
  2. lastModityTime不使用Mysql自动更新方式,而由Java Bean赋值方式。这样是最合理的。

mysql时间类型和java时间类对应关系

MySQL 类型 java类型
datetime java.sql.Timestamp
date java.sql.Date 或java.time.LocalDate
timestamp java.sql.Timestamp或java.time. LocalDateTime
time java.sql.Time 或java.time.LocalTime

通过org.apache.ibatis.type包下的类型解析器可得

mybatis处理java时间类和mysql时间类型方式

在org.apache.ibatis.type包下默认设置很多种类型,用于映射这映射关系。
比如挺好感觉Intant的类映射InstantTypeHandler类,类将java.time.intant转换成java.sql.timestamp


import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.time.Instant;
@UsesJava8
public class InstantTypeHandler extends BaseTypeHandler<Instant> {//将Instant转换成Timestamp。注意将instant表示的UTC时间转换成了当前时区的时间@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, Instant parameter, JdbcType jdbcType) throws SQLException {ps.setTimestamp(i, Timestamp.from(parameter));}//获得的数据又转换成Instant时间类private static Instant getInstant(Timestamp timestamp) {if (timestamp != null) {return timestamp.toInstant();}return null;}}

LocalDateTimeTypeHandler类

/***    Copyright 2009-2017 the original author or authors.**    Licensed under the Apache License, Version 2.0 (the "License");*    you may not use this file except in compliance with the License.*    You may obtain a copy of the License at**       http://www.apache.org/licenses/LICENSE-2.0**    Unless required by applicable law or agreed to in writing, software*    distributed under the License is distributed on an "AS IS" BASIS,*    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.*    See the License for the specific language governing permissions and*    limitations under the License.*/
package org.apache.ibatis.type;import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.time.LocalDateTime;import org.apache.ibatis.lang.UsesJava8;/*** @since 3.4.5* @author Tomas Rohovsky*/
@UsesJava8
public class LocalDateTimeTypeHandler extends BaseTypeHandler<LocalDateTime> {@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, LocalDateTime parameter, JdbcType jdbcType)throws SQLException {ps.setTimestamp(i, Timestamp.valueOf(parameter));}@Overridepublic LocalDateTime getNullableResult(ResultSet rs, String columnName) throws SQLException {Timestamp timestamp = rs.getTimestamp(columnName);return getLocalDateTime(timestamp);}@Overridepublic LocalDateTime getNullableResult(ResultSet rs, int columnIndex) throws SQLException {Timestamp timestamp = rs.getTimestamp(columnIndex);return getLocalDateTime(timestamp);}@Overridepublic LocalDateTime getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {Timestamp timestamp = cs.getTimestamp(columnIndex);return getLocalDateTime(timestamp);}private static LocalDateTime getLocalDateTime(Timestamp timestamp) {if (timestamp != null) {return timestamp.toLocalDateTime();}return null;}
}

其它类省略

JDBC连接数据库设置时区

使用JDBC连接数据库里5.7版本使用com.mysql.cj.jdbc.Driver 驱动包。在连接连接时要统一时区,否则容易造成混乱。
下面是设置方法

  1. UTC时间:serverTimezone=UTC
  2. 北京时间:
//北京时间东八区
serverTimezone=GMT%2B8
//或者使用上海时间
serverTimezone=Asia/Shanghai

完整例子
UTC时间

driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: root
jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=true

北京时间:

driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: root
jdbc:mysql://127.0.0.1:3306/test?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&useSSL=true

总结

以springboot框架开发javaweb项目为便,统一时间设置为UTC时间

mysql数据库里

字段指定了datetime或timestamp都一样,推荐使用timestamp

timestamp有自动初始化和更新,当你update某条记录的时候,该列值会自动更新,这是和datatime最大的区别。

javaweb

下面的2种情况其实都会使用到,在混合使用的情况

直接写sql情况下

mybatis的映射mapper文件的sql里使用UTC_TIMESTAMP代替CURRENT_TIMESTAMP。比如

<insert id="save" useGeneratedKeys="true" keyProperty="uid">insert into testTable ( create_a) values (UTC_TIMESTAMP )</insert>

使用javabean传递时间

在连接mysql数据库时统一时区为UTC

jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=true

其它

有人说要统一服务器时间,配置如下

@SpringBootApplicationpublic class Application {@PostConstructvoid started() {TimeZone.setDefault(TimeZone.getTimeZone("UTC"));}public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

但我没有使用也可以,先记录下吧

经过上面2种处理后,数据库时间就统一为UTC时间了,当然,这里涉及了mybatis的typeHandler处理,还是要学习的。
参考SpringBoot 统一时区的方案

统一javaweb项目和mysql数据库时间UTC时间方法及原理相关推荐

  1. mysql数据库怎么插入时间_给mysql数据库插入当前时间

    mysql相关的三个函数有: NOW()函数以`'YYYY-MM-DD HH:MM:SS'返回当前的日期时间,可以直接存到DATETIME字段中. CURDATE()以'YYYY-MM-DD'的格式返 ...

  2. Intellj IDEA添加MySQL数据库以及项目连接Mysql数据库

    添加数据库 View->Tool Windows->datebase->"+"->Data Source->MySQL 输入自己MySQL用户名和密码 ...

  3. 【MySQL】查看 mysql 数据库最后修改时间、创建时间、表大小

    查看 mysql 数据库最后修改时间.创建时间.表大小 一个库有几十张表,有很多这样的库. 想要查询一个库最近一次修改的时间,用以判断哪个是最近在使用的库. 有什么办法可以查询一个库最近一次修改的时间 ...

  4. node+express项目链接MySQL数据库(最简单版)

    node+express项目链接MySQL数据库(最简单版) (假定你node+express项目已创建完成,可参照这里) 第一步.安装mysql驱动 npm install mysql --save ...

  5. 阿里云服务器CentOS8 搭建javaweb环境及mysql数据库安装

    阿里云服务器CentOS8 搭建javaweb环境及mysql数据库安装 一. JavaWeb环境搭建 步骤1:登录 Linux 实例 1.使用标准方式登录 Linux 实例(推荐) 浏览器直接搜索阿 ...

  6. IDEA项目连接MySQL数据库

    IDEA项目连接MySQL数据库 一.前提 电脑已经安装好IntelliJ IDEA.MySQL和SQLyog并配置好,博主使用版本: 1)IntelliJ IDEA 2018.2.2 2)MySQL ...

  7. java maven项目连接mysql数据库

    实现maven项目连接mysql数据库 在maven项目下新建class文件,编辑该文件,部分具体代码如下: import java.sql.Connection; import java.sql.D ...

  8. ASP.NET Core Web项目连接MySQL数据库

    作者在新建了一个ASP.NET Core Web项目的基础上,想连接本地的Mysql数据库,参考了很多博客,各种各样的说法都有,多少让人有感凌乱!自己最后捣鼓成功了!所以写一篇博客,以便后人查阅! 操 ...

  9. linux mysql数据库优化_MySQL_Linux下MySQL数据库性能调优方法,以下的环境具备一定的代表性 - phpStudy...

    Linux下MySQL数据库性能调优方法 以下的环境具备一定的代表性,可以说是中小企业一般配置和工作环境.希望通过本文能让大家理解Linux下MySQL数据库性能调优方法. 硬件准备环境: 硬盘: 1 ...

最新文章

  1. 微信小程序修改整体背景颜色
  2. ElasticSearch+ElasticGeo+Geoserver发布ES地理数据
  3. vue组件化学习第三天
  4. Vijos P1756 数字反转【进制】
  5. Apache Kafka-通过设置Consumer Group实现广播模式
  6. SQL 重置自增列的值 批量处理
  7. fir.im Weekly - 2017 年必须了解的 iOS 开源库
  8. SQLAlchemy 教程 —— ORM 方式使用示例
  9. uni-app中的tabBar配置
  10. Java程序性能优化:让你的Java程序更快、更稳定
  11. Nmap内网扫描端口
  12. Docker上安装DM8数据库
  13. 联想Y430P CentOS 7.3 无线网络的配置
  14. 推荐几款实用的思维导图工具
  15. Google如何在新标签打开页面打开链接?
  16. 身份证 闰年验证 超强验证
  17. 记一次ios内购开发中踩的坑
  18. 如何在CSDN中发布文章
  19. 21. 程序员生存定律-选公司前要干的事:分类
  20. 活灵活现用Git--基础篇

热门文章

  1. Postgre SQL修改字段类型语法
  2. 2022 年全国职业院校技能大赛高职组云计算赛项赛题解析-“私有云 赛项” 之 《私有云运维开发》!!超详细!
  3. iops oracle 视图,Oracle 12C R2-新特性-PDB的磁盘I/O(IOPS,MBPS)资源管理
  4. java+ssh+mysql新闻网站
  5. 软件随想录(local.joelonsoftware.com/wiki)-2005年06月20日 最佳软件文选I - 介绍 - Introduction to Best Software Writin
  6. Zookeeper 4 Zookeeper JavaAPI 操作 4.9 模拟12306 售票案例
  7. HTTP客户端Fegin
  8. AAAI 2021 | 在手机上实现19FPS实时的YOLObile目标检测
  9. 前端优化-图片打包处理base64的原因
  10. IDEA配置git详细步骤