为什么存入mysql数据库中的timestamp,晚了13或14个小时

使用markdown,方便大家浏览,就又更新了一下

查看数据库时区

show variables like '%time_zone%';

select @@global.system_time_zone;

select @@global.time_zone;

可以得到默认数据库时区:

system_time_zone | CST |

time_zone | SYSTEM|

CST时区:4个含义

CST可以为如下4个不同的时区的缩写:

1,美国中部时间:Central Standard Time (USA) UT-6:00 ,又美国从“3月11日”至“11月7日”实行夏令时,美国中部时间改为 UT-05:00

2,澳大利亚中部时间:Central Standard Time (Australia) UT+9:30

3,中国标准时间:China Standard Time UT+8:00

4,古巴标准时间:Cuba Standard Time UT-4:00

PS:即中国标准时间UT+8,和美国UT-5,中间相差13个小时

查看java程序运行的本地时区

TimeZone.getDefault();//得到"Asia/Shanghai"

debug与源码分析:

1,测试发现,客户端到java程序端的时间戳是正确的,即通过mybatis写入数据库之前时间戳是正确的

2,从mybatis一路跟踪:mybatis SqlTimestampTypeHandler.setNonNullParameter()->mybatis PreparedStatement.setTimestamp-》mysql-connector preparedStatement.setTimestamp()-》preparedStatement.setTimestampInternal()-》TimeUtil.changTimestamp(),通过计算本地时区和数据库时区差值,得到数据的时间戳,再转成SimpleDateFormat.format yyyy-MM-dd HH:mm:ss格式的时间戳日期字符串,写入数据库

3,问题:java运行的本地时区是"Asia/Shanghai",那mysql-connector得到的数据库时区是什么样的?连接数据库的时候,mysql-connector会获取数据库的时区信息,如上数据库时区查询,得到SYSTEM,CST

mysql-connector获取数据库时区

1,CST 的时区是一个很混乱的时区,在与 MySQL 协商会话时区时,Java 会误以为是 CST -0500,而非 CST +0800

private void configureTimezone() throws SQLException {

String configuredTimeZoneOnServer = (String) this.serverVariables

.get("timezone");

if (configuredTimeZoneOnServer == null) {

configuredTimeZoneOnServer = (String) this.serverVariables

.get("time_zone");

if ("SYSTEM".equalsIgnoreCase(configuredTimeZoneOnServer)) {

configuredTimeZoneOnServer = (String) this.serverVariables

.get("system_time_zone");//得到CST,mysql-connector以为的CST是美国的CST-5:00

}

}

...

}

2,TimeZone.getTimeZone(canonicalTimezone)得到CST,mysql-connector以为的CST是美国的CST-5:00,{"CST", "America/Chicago"}

3,mysql-connector ZoneInfoFile class时区简写和时区对应关系

{{"ACT", "Australia/Darwin"},

{"AET", "Australia/Sydney"},

{"AGT", "America/Argentina/Buenos_Aires"},

{"ART", "Africa/Cairo"},

{"AST", "America/Anchorage"},

{"BET", "America/Sao_Paulo"},

{"BST", "Asia/Dhaka"},

{"CAT", "Africa/Harare"},

{"CNT", "America/St_Johns"},

{"CST", "America/Chicago"},

{"CTT", "Asia/Shanghai"},

{"EAT", "Africa/Addis_Ababa"},

{"ECT", "Europe/Paris"},

{"IET", "America/Indiana/Indianapolis"},

{"IST", "Asia/Kolkata"},

{"JST", "Asia/Tokyo"},

{"MIT", "Pacific/Apia"},

{"NET", "Asia/Yerevan"},

{"NST", "Pacific/Auckland"},

{"PLT", "Asia/Karachi"},

{"PNT", "America/Phoenix"},

{"PRT", "America/Puerto_Rico"},

{"PST", "America/Los_Angeles"},

{"SST", "Pacific/Guadalcanal"},

{"VST", "Asia/Ho_Chi_Minh"}};

如何解决

一,修改数据库时区

set global time_zone = '+8:00';//设置全局时区为东八区

set time_zone = '+8:00'; //

flush privileges;//刷新权限使设置立即生效

二,添加jdbc参数:serverTimezone=GMT%2B8

db?useUnicode=true&characterEncoding=UTF-8&useAffectedRows=true&useTimezone=true&serverTimezone=GMT%2B8

会有什么问题

1,因为老数据是基于CST-5:00,得到的时间戳日期字符串(yyyy-MM-dd HH:mm:ss.SSS),写入数据库中,改了数据库时区或修改了JDBC的时区配置,会导致旧数据比以前慢13个小时

那旧数据怎么办

1,创建一个mybatis TimstampTypehandler专门处理timestamp类型,将某个时间以前的时间戳加上13个小时的时间戳间隔,即可

@MappedJdbcTypes(JdbcType.TIMESTAMP)

@MappedTypes(Timestamp.class)

public class TimestampHandler extends SqlTimestampTypeHandler {

@Override

public void setNonNullParameter(PreparedStatement ps, int i, Timestamp parameter, JdbcType jdbcType)

throws SQLException {

ps.setTimestamp(i, parameter);

}

@Override

public Timestamp getNullableResult(ResultSet rs, String columnName)

throws SQLException {

//TimeZone tz=TimeZone.getDefault();

//TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));

Timestamp timestampTemp=rs.getTimestamp(columnName);

long lt=timestampTemp.getTime();

long timestampSplit=1590249600000L;//2020-05-24 00:00:00的毫秒时间戳

if(timestampSplit>lt){

Timestamp timestamp=new Timestamp(lt+13*60*60*1000);

return timestamp;

}else{

return timestampTemp;

}

}

@Override

public Timestamp getNullableResult(ResultSet rs, int columnIndex)

throws SQLException {

TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));

Timestamp timestampTemp=rs.getTimestamp(columnIndex);

long lt=timestampTemp.getTime();

long timestampSplit=1590249600000L;//2020-05-24 00:00:00的毫秒时间戳

if(timestampSplit>lt){

Timestamp timestamp=new Timestamp(lt+13*60*60*1000);

return timestamp;

}else{

return timestampTemp;

}

}

@Override

public Timestamp getNullableResult(CallableStatement cs, int columnIndex)

throws SQLException {

TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));

Timestamp timestampTemp=cs.getTimestamp(columnIndex);

long lt=timestampTemp.getTime();

long timestampSplit=1590249600000L;//2020-05-24 00:00:00的毫秒时间戳

if(timestampSplit>lt){

Timestamp timestamp=new Timestamp(lt+13*60*60*1000);

return timestamp;

}else{

return timestampTemp;

}

}

}

多人开发,timestamp时间戳使用规约

1,接口参数涉及时间,都用时间戳,精确到秒或毫秒,全项目统一

2,时间戳参数直接入库,不要在代码层再做一次SimpleDateFormat.format yyyy-MM-dd HH:mm:ss.SSS转换,这样会附加本地时区,导致时间戳失效,mysql connector在入库前对timestamp类型做了本地时区和数据库时区差值计算的

mysql时间戳13小时_为什么存入mysql数据库中的timestamp,晚了13或14个小时相关推荐

  1. mysql blob 写入表_文件存入MYSql表的blob

    向MYSql的数据表中存入文件,这看似没有什么大问题,只要把文件存入longblob字段就行了.但是最近的实践发现看似简单的背后其实有很多陷阱.下面就来分享一下我遇到的问题及我的解决办法. 先介绍一下 ...

  2. mysql时间戳的使用_如何使用MYSQL时间戳查询时间段

    使用MYSQL时间戳查询时间段的常用函数 UNIX_TIMESTAMP(date) 如果没有参数调用,返回一个Unix时间戳记(从'1970-01-01 00:00:00′GMT开始的秒数).如果UN ...

  3. mysql查询计算机系信息_在学生管理数据库中查询通信系和计算机系的所有教师信息...

    在学生管理数据库中查询通信系和计算机系的所有教师信息 答:select * from 教师 where 系部代码 in(select 系部代码 from 系部 where 系部名称 in('通信系', ...

  4. mysql查询课程最高分_在“成绩管理”数据库中,查询每门课程的最高分,要求得到的信息包括课程名称和分数。正确的命令是( )。 A.SELE_搜题易...

    统计只有2名以下(含2名)学生选修的课程情况,统计结果中的信息包括课程名称.开课院系和选修人数,并按选课人数排序.正确的命令是(  ). A.SELECT 课程名称,开课院系,COUNT(课程编号)A ...

  5. mysql数据库时间突然是12小时制_为什么存入mysql数据库中的timestamp,晚了13或14个小时...

    # 为什么存入mysql数据库中的timestamp,晚了13个小时 ## 查看数据库时区 ``` show variables like '%time_zone%'; select @@global ...

  6. c 将图片存入到mysql数据库中_如何将图片转换存入到数据库中,并从数据库中取出转换成图片...

    有时候我们想把图片存入到数据库中,尽管这不是一种明智的选择,但有时候还是不得以会用到,下面说说将图片转换成byte[]数组存入到数据库中去,并从数据库中取出来转换成图像显示出来. 首先,我们要把图片存 ...

  7. python爬虫爬取虎扑湖人论坛专区帖子数据,并存入MongoDB数据库中

    今天就带大家从头到尾一步一步带着大家爬取虎扑论坛帖子的数据,里面涉及到的一些知识,我会给出学习的连接,大家可以自行去学习查看. 前期准备 首先我们打开虎扑NBA论坛,我选择的是湖人专区(小湖迷一个). ...

  8. mysql 常规命令操作_常见的MySQL命令大全

    一.连接MySQL格式: mysql -h主机地址 -u用户名 -p用户密码1.例1:连接到本机上的MYSQL.首先在打开DOS窗口,然后进入目录 mysqlbin,再键入命令mysql -uroot ...

  9. mysql 数据库命令大全_常用的MySQL数据库命令大全

    飞信2017V5.6.8860.0 官方正式版 类型:聊天其它大小:69.1M语言:中文 评分:9.6 标签: 立即下载 常用的MySQL命令大全 一.连接MySQL 格式: mysql -h主机地址 ...

最新文章

  1. Springboot+mybatisplus搭建新闻管理系统
  2. curlopt_ssl_verifypeer后https还是验证不过_验证码识别竞赛解决方案(97%+一等奖)
  3. BZOJ1393 [Ceoi2008]knights
  4. socket(套接字)详解一种通讯机制
  5. php有哪些程序结构,PHP常用控制结构
  6. php声明js变量类型,js中变量是什么以及有哪些类型
  7. 【机器学习】输出层的设计
  8. web本地开发环境集成工具:​​​​MAMP Pro
  9. QTP11 5 HP UFT 11 5 下载地址
  10. 监控apache脚本原理
  11. 伽罗华有限域_信息论与编码:有限域
  12. 超级简单的HTML圆形头像css
  13. nodejs 系统 临时文件夹
  14. android 说出密码,小米路由器微信好友认证功能实际体验
  15. 解决方案——笔记本HDMI外接2k显示器如何调2k分辨率
  16. 企业知识管理包括哪些内容?
  17. 使用域名访问远程jupyter_如何设置远程访问的Jupyter Notebook服务器-01(之预备知识:什么是端口号?)...
  18. asp生成带参数的二维码并合成推广海报图片,asp合并合成推广海报图片asp代码...
  19. Verilog自制NIOS2外设,Avalon总线上的HelloWorld
  20. 什么人适合考国家注册审核员呢

热门文章

  1. 禁用剪贴板html如何复制,如何在按钮单击时将干净的HTML复制到剪贴板?
  2. count(1)、count(*)、count(列名)的区别
  3. 入驻CSDN博客心情
  4. 说说我们项目组的例行会议 (转)
  5. Autodesk 3sd max 2013 x64正确下载安装激活操作,官方中文版+英文版下载
  6. python接收广播_有效处理市场广播数据并使用python进行处理
  7. Spark的broadcast
  8. VUE3 之 多个 v-model 绑定及 v-model 修饰符的使用
  9. 本地连接受限制或未连接怎么办
  10. 服务器tomcat网络不稳定,tomcat服务器tcp连接出现大量ESTABLISHED连接导致前端访问502解决方法...