背景 公司各个项目组用的mysql 版本不一样,有的是5.x稳定守旧版,有的最近喜欢用8.x高级迎新版,结果出了问题。
现象,数据库中保存的时间与java读取的时间字段不一样。
最开始数据库mysql版本为5.7.28,驱动为5.1 反正5.x都没什么问题。
数据库时区为 show variables like '%zone%'

现在有人使用mysql 8.x的版本,项目中就使用8.x的驱动

导致的问题就是时间字段不一致!!而且读取的时候还出问题了。
Caused by: com.mysql.cj.exceptions.WrongArgumentException: HOUR_OF_DAY: 2 -> 3
举例 数据库为5.x版本,数据库存放数据

我使用5.x的驱动
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
得到结果:id=8637200,last_update_date2021-03-13 14:03:54.0
使用8.x的驱动
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
<!-- <version>5.1.49</version>-->
</dependency>
得到结果:id=8637200,last_update_date2021-03-14 04:03:54.0
相差时间有10个小时,其中有同事遇到过相差13个小时的,这种肯定就是时区问题了
java.sql.SQLException: HOUR_OF_DAY: 2 -> 3_-兰天白云-的博客-CSDN博客
解决办法分为几种
1. mysql-connector-java.jar版本6.x、8.x降级为5.1.x
2. 对于高版本jdbc,连接串强制指定时区参数:serverTimezone=GMT%2B8
这个第二点有人说serverTimezone=Asia/Shanghai。
3. 对于高版本jdbc,mysql数据库强制修改time_zone为“+8:00”,而非“SYSTEM
第一点 经过之前测试降级没有问题。我用5.1的驱动连接没问题。
第二点 那种才是正确的呢?
serverTimezone=Asia/Shanghai 的结果是正确的
id=8637200,last_update_date2021-03-13 14:03:54.0
serverTimezone=GMT%2B8 的结果也是正确的。
id=8637200,last_update_date2021-03-13 14:03:54.0
怪我经验太少 都是中国的。。但是一个是shanghai一个是2B8。。。差的太多了
//北京时间东八区
serverTimezone=GMT%2B8
//上海时间
serverTimezone=Asia/Shanghai

下面我来好好学习下时区,以及为什么会出现这个问题。
先学习下时区的基本信息UTC GMT EST CST 区别_cst est_天已青色等烟雨来的博客-CSDN博客
- GMT - (Greenwich Mean Time)的缩写,指的是皇家格林威治天文台的标准时间,称作格林威治时间,因为本初子午线通过此地区,因此也称为世界标准时间。然而地球的自转不是完全规律的,而且正逐渐减慢,因此自1924年开始,格林威治时间(GMT)已经不再被视为标准时间,取而代之的是"世界协调时间" (UTC: Coordinated Universal Time)
- UTC - 协调世界时(Coordinated Universal Time)是最主要的世界时间标准,其以原子时秒长为基础,在时刻上尽量接近于格林尼治标准时间。UTC 是一个标准,而不是一个时区
- CST - 北京时间,China Standard Time,中国标准时间,是中国的标准时间。在时区划分上,属东八区,比协调世界时早8小时,记为UTC+8
- EST - 和CST一样,是众多时区中的一种时区。
| 缩写 | 全称 | 中文名称 | 类型 | UTC 偏移量 |
|---|---|---|---|---|
| +03 | +03 | - | UTC +03:00 | |
| +04 | +04 | - | UTC +04:00 | |
| +05 | +05 | - | UTC +05:00 | |
| +0530 | +0530 | - | UTC +05:30 | |
| +06 | +06 | - | UTC +06:00 | |
| ACDT | Australian Central Daylight Time | 澳大利亚中部夏令时 | 夏令时 | UTC +10:30 |
| ACST | Australian Central Standard Time | 澳大利亚中部标准时间 | - | UTC +09:30 |
| ACT | Acre Time | 阿卡时间 | - | UTC -05:00 |
| ACWST | Australian Central Western Standard Time | 澳大利亚中西部标准时间 | - | UTC +08:45 |
| ADT | Atlantic Daylight Time | 大西洋夏令时间 | 夏令时 | UTC -03:00 |
| AEDT | Australian Eastern Daylight Time | 澳大利亚东部夏令时 | 夏令时 | UTC +11:00 |
| AEST | Australian Eastern Standard Time | 澳大利亚东部标准时间 | - | UTC +10:00 |
| AFT | Afghanistan Time | 阿富汗时间 | - | UTC +04:30 |
| AKDT | Alaska Daylight Time | 阿拉斯加夏令时 | 夏令时 | UTC -08:00 |
| AKST | Alaska Standard Time | 阿拉斯加标准时间 | - | UTC -09:00 |
| AMST | Amazon Summer Time | 亚马逊夏令时 | 夏令时 | UTC -03:00 |
| AMT | Amazon Time | 亚马逊时间 | - | UTC -04:00 |
| ART | Argentina Time | 阿根廷时间 | - | UTC -03:00 |
| AST | Arabia Standard Time | 阿拉伯标准时间 | - | UTC +03:00 |
| AST | Atlantic Standard Time | 大西洋标准时间 | - | UTC -04:00 |
| AWST | Australian Western Standard Time | 澳大利亚西部标准时间 | - | UTC +08:00 |
| AZOST | Azores Summer Time | 亚速尔群岛夏令时 | 夏令时 | UTC -00:00 |
| AZOT | Azores Time | 亚速尔群岛时间 | - | UTC -01:00 |
| BOT | Bolivia Time | 玻利维亚时间 | - | UTC -04:00 |
| BRST | Brasília Summer Time | 巴西利亚夏令时 | 夏令时 | UTC -02:00 |
| BRT | Brasília Time | 巴西利亚时间 | - | UTC -03:00 |
| BST | British Summer Time | 英国夏令时间 | 夏令时 | UTC +01:00 |
| BTT | Bhutan Time | 不丹时间 | - | UTC +06:00 |
| CAT | Central Africa Time | 中非时间 | - | UTC +02:00 |
| CDT | Central Daylight Time | 中部夏令时间 | 夏令时 | UTC -05:00 |
| CDT | Cuba Daylight Time | 古巴夏令时 | 夏令时 | UTC -04:00 |
| CEST | Central European Summer Time | 欧洲中部夏令时间 | 夏令时 | UTC +02:00 |
| CET | Central European Time | 欧洲中部时间 | - | UTC +01:00 |
| CHADT | Chatham Island Daylight Time | 查塔姆岛夏令时 | 夏令时 | UTC +13:45 |
| CHAST | Chatham Island Standard Time | 查塔姆岛标准时间 | - | UTC +12:45 |
| CHOST | Choibalsan Summer Time | 乔巴山夏令时 | 夏令时 | UTC +09:00 |
| CHOT | Choibalsan Time | 乔巴山时间 | - | UTC +08:00 |
| CHUT | Chuuk Time | 丘克时间 | - | UTC +10:00 |
| CKT | Cook Island Time | 库克群岛时间 | - | UTC -10:00 |
| CLST | Chile Summer Time | 智利夏令时 | 夏令时 | UTC -03:00 |
| CLT | Chile Standard Time | 智利标准时间 | - | UTC -04:00 |
| CST | Central Standard Time | 中部标准时间 | - | UTC -06:00 |
| CST | China Standard Time | 中国标准时间 | - | UTC +08:00 |
| CST | Cuba Standard Time | 古巴标准时间 | - | UTC -05:00 |
| ChST | Chamorro Standard Time | 查莫罗标准时间 | - | UTC +10:00 |
| EASST | Easter Island Summer Time | 复活岛夏令时 | 夏令时 | UTC -05:00 |
| EAST | Easter Island Standard Time | 复活节岛标准时间 | - | UTC -06:00 |
| EAT | Eastern Africa Time | 非洲东部时间 | - | UTC +03:00 |
| ECT | Ecuador Time | 厄瓜多尔时间 | - | UTC -05:00 |
| EDT | Eastern Daylight Time | 东部夏令时间 | 夏令时 | UTC -04:00 |
| EEST | Eastern European Summer Time | 东欧夏令时 | 夏令时 | UTC +03:00 |
| EET | Eastern European Time | 东欧时间 | - | UTC +02:00 |
| EST | Eastern Standard Time | 东部标准时间 | - | UTC -05:00 |
| FKST | Falkland Islands Summer Time | 福克兰群岛夏令时 | - | UTC -03:00 |
| GFT | French Guiana Time | 法属圭亚那时间 | - | UTC -03:00 |
| GILT | Gilbert Island Time | 吉尔伯特群岛时间 | - | UTC +12:00 |
| GMT | Greenwich Mean Time | 格林威治标准时间 | - | UTC -00:00 |
| GST | Gulf Standard Time | 海湾标准时间 | - | UTC +04:00 |
| HKT | Hong Kong Time | 香港时间 | - | UTC +08:00 |
| HST | Hawaii Standard Time | 夏威夷标准时间 | - | UTC -10:00 |
| ICT | Indochina Time | 印度支那时间 | - | UTC +07:00 |
| IDT | Israel Daylight Time | 以色列夏令时 | 夏令时 | UTC +03:00 |
| IRDT | Iran Daylight Time | 伊朗夏令时 | 夏令时 | UTC +04:30 |
| IRST | Iran Standard Time | 伊朗标准时间 | - | UTC +03:30 |
| IST | India Standard Time | 印度标准时间 | - | UTC +05:30 |
| IST | Irish Standard Time | 爱尔兰标准时间 | 夏令时 | UTC +01:00 |
| IST | Israel Standard Time | 以色列标准时间 | - | UTC +02:00 |
| JST | Japan Standard Time | 日本标准时间 | - | UTC +09:00 |
| KOST | Kosrae Time | 科斯雷时间 | - | UTC +11:00 |
| KST | Korea Standard Time | 韩国标准时间 | - | UTC +08:30 |
| LINT | Line Islands Time | 莱恩群岛时间 | - | UTC +14:00 |
| MDT | Mountain Daylight Time | 山区夏令时 | 夏令时 | UTC -06:00 |
| MHT | Marshall Islands Time | 马绍尔群岛时间 | - | UTC +12:00 |
| MSK | Moscow Standard Time | 莫斯科标准时间 | - | UTC +03:00 |
| MST | Mountain Standard Time | 山地标准时间 | - | UTC -07:00 |
| MYT | Malaysia Time | 马来西亚时间 | - | UTC +08:00 |
| NDT | Newfoundland Daylight Time | 纽芬兰夏令时 | 夏令时 | UTC -02:30 |
| NPT | Nepal Time | 尼泊尔时间 | - | UTC +05:45 |
| NST | Newfoundland Standard Time | 纽芬兰标准时间 | - | UTC -03:30 |
| NUT | Niue Time | 纽埃时间 | - | UTC -11:00 |
| NZDT | New Zealand Daylight Time | 新西兰夏令时 | 夏令时 | UTC +13:00 |
| NZST | New Zealand Standard Time | 新西兰标准时间 | - | UTC +12:00 |
| PDT | Pacific Daylight Time | 太平洋夏令时 | 夏令时 | UTC -07:00 |
| PET | Peru Time | 秘鲁时间 | - | UTC -05:00 |
| PGT | Papua New Guinea Time | 巴布亚新几内亚时间 | - | UTC +10:00 |
| PHT | Philippine Time | 菲律宾时间 | - | UTC +08:00 |
| PKT | Pakistan Standard Time | 巴基斯坦标准时间 | - | UTC +05:00 |
| PONT | Pohnpei Standard Time | 波纳佩标准时间 | - | UTC +11:00 |
| PST | Pacific Standard Time | 太平洋标准时间 | - | UTC -08:00 |
| SAST | South Africa Standard Time | 南非标准时间 | - | UTC +02:00 |
| SBT | Solomon Islands Time | 所罗门群岛时间 | - | UTC +11:00 |
| SGT | Singapore Time | 新加坡时间 | - | UTC +08:00 |
| SRT | Suriname Time | 苏里南时间 | - | UTC -03:00 |
| SST | Samoa Standard Time | 萨摩亚标准时间 | - | UTC -11:00 |
| TAHT | Tahiti Time | 塔希提岛时间 | - | UTC -10:00 |
| TLT | East Timor Time | 东帝汶时间 | - | UTC +09:00 |
| TVT | Tuvalu Time | 图瓦卢时间 | - | UTC +12:00 |
| ULAST | Ulaanbaatar Summer Time | 乌兰巴托夏令时 | 夏令时 | UTC +09:00 |
| ULAT | Ulaanbaatar Time | 乌兰巴托时间 | - | UTC +08:00 |
| UYST | Uruguay Summer Time | 乌拉圭夏令时 | 夏令时 | UTC -02:00 |
| UYT | Uruguay Time | 乌拉圭时间 | - | UTC -03:00 |
| VET | Venezuelan Standard Time | 委内瑞拉标准时间 | - | UTC -04:00 |
| WAST | West Africa Summer Time | 西非夏令时 | 夏令时 | UTC +02:00 |
| WAT | West Africa Time | 西非时间 | - | UTC +01:00 |
| WEST | Western European Summer Time | 西欧夏令时间 | 夏令时 | UTC +01:00 |
| WET | Western European Time | 西欧时间 | - | UTC -00:00 |
| WIB | Western Indonesian Time | 印尼西部时间 | - | UTC +07:00 |
| WIT | Eastern Indonesian Time | 印度尼西亚东部时间 | - | UTC +09:00 |
| WITA | Central Indonesian Time | 印度尼西亚中部时间 | - | UTC +08:00 |
注意这里上面的有三个CST!!
说下时区的注意点。
在中国新疆哈密是东六区到北京是东八区,从西到东有2个小时的时差,
在美国从东向西分别为东部时间(EST)(西五区时间)、中部时间(CST)(西六区时间)、山地时间(MST)(西七区时间)、太平洋时间(西部时间)(PST)(西八区时间)、阿拉斯加时间(AKST)(西九区时间)和夏威夷时间(HST)(西十区时间)
但是这个时差在中国为啥不明显,因为在中国这个时间统一了,比如北京八点上班,此时按照时区时间新疆是6点,时间也差不了太多,所以可以看作中国无时差,无时区。
但是在美国不一样,时差由政府把握,也即是我们说的每到一个时区,你需要把手表时间快或慢一小时。
再补充学习下夏令时的概念。
夏令时_百度百科

注意对于夏令时各个国家也有不同的做法。
中国1992年起,夏令时暂停实行。
俄罗斯自从2011年3月27日开始永久使用夏令时,把时间拨快一小时,不再调回。
美国夏时制的实行与否,完全由各州、各县自行决定,不由联邦政府统一规定。目前美国绝大部分地区实行夏令时。
此时举个例子,
我们现在是东八区,美国华盛顿是西五区,此时时差应该是(东8-西5-中时区)=13个小时
因为有夏令时的存在,华盛顿西五区要快1小时,变成了西四区,所以现在的时差如下=12小时

此时回头看下我们数据 2021-03-13 14:03:54.0和2021-03-14 04:03:54.0 相差了10个小时好像和12/13对不上?接着学习。
夏令时:
由于美国有夏令时,CST非夏令时对应 UTC-06:00,夏令时对应 UTC-05:00 。
美国的夏令时,从每年3月第2个星期天凌晨开始,到每年11月第1个星期天凌晨结束。
以2020年为例: 3月第2个星期天为3月8号

夏令时开始时间调整前:2020年03月08日星期日 02:00:00,时间向前拨一小时.
调整后:2020年03月08日星期日 03:00:00
夏令时结束时间调整前:2020年11月01日星期日 02:00:00,时间往回拨一小时.
调整后:2020年11月01日星期日 01:00:00
这意味这:CST没有2020-03-08 02:00:00~2020-03-08 03:00:00 这个区间的时间。会有两个 2020-11-01 01:00:00~2020-11-01 02:00:00区间的时间
说实话这里我都有点乱了。
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("CST"), Locale.US);
calendar.setLenient(false);//容错模式 例如分钟1000会进位到小时
//2020-03-08 01:02:00
calendar.set(2020, 2, 8, 1, 2, 0);
Date date1 = new Date(calendar.getTimeInMillis());
String format = f1.format(date1);
System.out.println("设置时间为 2020-03-08 01:02:00," + "CST时区时间为 " + format);
//2020-03-08 01:02:00 非夏令时间,于北京时间相差14小时。
//2020-03-08 03:02:00
calendar.set(2020, 2, 8, 3, 2, 0);
Date date3 = new Date(calendar.getTimeInMillis());
String format3 = f1.format(date3);
System.out.println("设置时间为 2020-03-08 03:02:00," + "CST时区时间为 " + format3);
//2020-03-08 03:02:00 夏令时间,于北京时间相差13小时。
//抛出 Exception: HOUR_OF_DAY: 2 -> 3
//2020-03-08 02:02:00
calendar.set(2020, 2, 8, 2, 2, 0);
//抛出异常:java.lang.IllegalArgumentException: HOUR_OF_DAY: 2 -> 3
Date error = new Date(calendar.getTimeInMillis());
String format2 = f1.format(error);
System.out.println("设置时间为 2020-03-08 03:02:00," + "CST时区时间为 " + format2);
}
设置时间为 2020-03-08 01:02:00,CST时区时间为 2020-03-08 15:02:00
设置时间为 2020-03-08 03:02:00,CST时区时间为 2020-03-08 16:02:00
Exception in thread "main" java.lang.IllegalArgumentException: HOUR_OF_DAY: 2 -> 3
at java.util.GregorianCalendar.computeTime(GregorianCalendar.java:2829)
at java.util.Calendar.updateTime(Calendar.java:3393)
at java.util.Calendar.getTimeInMillis(Calendar.java:1782)
at com.chenchi.learning.java.calender.CalenderTest.main(CalenderTest.java:66)
这里有个问题 我在中国默认的timeZone为 Asia/Shanghai。
上面设置的CST是啥?
美国中部时间 Central Standard Time (USA) UTC-05:00 / UTC-06:00
澳大利亚中部时间 Central Standard Time (Australia) UTC+09:30 --这个上面又是 ACST
中国标准时间 China Standard Time UTC+08:00
古巴标准时间 Cuba Standard Time UTC-04:00
我他妈也是服了,每个人说的不一样,不过按照结果来说 java代码里应该是美国的UTC-5/6,注意本来是CST的 因为现在是夏天所以又是CDT。
此时有点晕了 理一理。
UTC=GMT 可以理解吧
GMT: 格林威治标准时间,英国伦敦格林威治定为 0° 经线开始的地方,地球每 15° 经度 被分为一个时区,共分为 24 个时区,相邻时区相差一小时。
UTC:世界协调时间,经严谨计算得到的时间,精确到秒,误差在 0.9s 以内, 是比 GMT 更为精确的世界时间。
东八区就是中国标准时间,它也是相对 GMT 而言的。所以,我们平时碰到相差 8 小时问题,就是因为中国标准时间和 GTM 相差 8 个时区,也就是相差 8 小时。
再来看 CST,百度百科里说 CST可视为中国、古巴的标准时间或美国、澳大利亚的中部时间,
这他m的一个CST代表四个不同的时区,怎么代表?
我们说的
美国本土横跨西五区至西八区,共四个时区,每个时区对应一个标准时间。从东向西分别为东部时间(EST)(西五区时间)、中部时间(CST)(西六区时间)、山地时间(MST)(西七区时间)、太平洋时间(西部时间)(PST)(西八区时间)。
又因为夏令时的存在CST!=GMT-6。
搞不动了。。



















