mysql版本升级导致的时区问题

背景 公司各个项目组用的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
ACDTAustralian Central Daylight Time澳大利亚中部夏令时夏令时UTC +10:30
ACSTAustralian Central Standard Time澳大利亚中部标准时间-UTC +09:30
ACTAcre Time阿卡时间-UTC -05:00
ACWSTAustralian Central Western Standard Time澳大利亚中西部标准时间-UTC +08:45
ADTAtlantic Daylight Time大西洋夏令时间夏令时UTC -03:00
AEDTAustralian Eastern Daylight Time澳大利亚东部夏令时夏令时UTC +11:00
AESTAustralian Eastern Standard Time澳大利亚东部标准时间-UTC +10:00
AFTAfghanistan Time阿富汗时间-UTC +04:30
AKDTAlaska Daylight Time阿拉斯加夏令时夏令时UTC -08:00
AKSTAlaska Standard Time阿拉斯加标准时间-UTC -09:00
AMSTAmazon Summer Time亚马逊夏令时夏令时UTC -03:00
AMTAmazon Time亚马逊时间-UTC -04:00
ARTArgentina Time阿根廷时间-UTC -03:00
ASTArabia Standard Time阿拉伯标准时间-UTC +03:00
ASTAtlantic Standard Time大西洋标准时间-UTC -04:00
AWSTAustralian Western Standard Time澳大利亚西部标准时间-UTC +08:00
AZOSTAzores Summer Time亚速尔群岛夏令时夏令时UTC -00:00
AZOTAzores Time亚速尔群岛时间-UTC -01:00
BOTBolivia Time玻利维亚时间-UTC -04:00
BRSTBrasília Summer Time巴西利亚夏令时夏令时UTC -02:00
BRTBrasília Time巴西利亚时间-UTC -03:00
BSTBritish Summer Time英国夏令时间夏令时UTC +01:00
BTTBhutan Time不丹时间-UTC +06:00
CATCentral Africa Time中非时间-UTC +02:00
CDTCentral Daylight Time中部夏令时间夏令时UTC -05:00
CDTCuba Daylight Time古巴夏令时夏令时UTC -04:00
CESTCentral European Summer Time欧洲中部夏令时间夏令时UTC +02:00
CETCentral European Time欧洲中部时间-UTC +01:00
CHADTChatham Island Daylight Time查塔姆岛夏令时夏令时UTC +13:45
CHASTChatham Island Standard Time查塔姆岛标准时间-UTC +12:45
CHOSTChoibalsan Summer Time乔巴山夏令时夏令时UTC +09:00
CHOTChoibalsan Time乔巴山时间-UTC +08:00
CHUTChuuk Time丘克时间-UTC +10:00
CKTCook Island Time库克群岛时间-UTC -10:00
CLSTChile Summer Time智利夏令时夏令时UTC -03:00
CLTChile Standard Time智利标准时间-UTC -04:00
CSTCentral Standard Time中部标准时间-UTC -06:00
CSTChina Standard Time中国标准时间-UTC +08:00
CSTCuba Standard Time古巴标准时间-UTC -05:00
ChSTChamorro Standard Time查莫罗标准时间-UTC +10:00
EASSTEaster Island Summer Time复活岛夏令时夏令时UTC -05:00
EASTEaster Island Standard Time复活节岛标准时间-UTC -06:00
EATEastern Africa Time非洲东部时间-UTC +03:00
ECTEcuador Time厄瓜多尔时间-UTC -05:00
EDTEastern Daylight Time东部夏令时间夏令时UTC -04:00
EESTEastern European Summer Time东欧夏令时夏令时UTC +03:00
EETEastern European Time东欧时间-UTC +02:00
ESTEastern Standard Time东部标准时间-UTC -05:00
FKSTFalkland Islands Summer Time福克兰群岛夏令时-UTC -03:00
GFTFrench Guiana Time法属圭亚那时间-UTC -03:00
GILTGilbert Island Time吉尔伯特群岛时间-UTC +12:00
GMTGreenwich Mean Time格林威治标准时间-UTC -00:00
GSTGulf Standard Time海湾标准时间-UTC +04:00
HKTHong Kong Time香港时间-UTC +08:00
HSTHawaii Standard Time夏威夷标准时间-UTC -10:00
ICTIndochina Time印度支那时间-UTC +07:00
IDTIsrael Daylight Time以色列夏令时夏令时UTC +03:00
IRDTIran Daylight Time伊朗夏令时夏令时UTC +04:30
IRSTIran Standard Time伊朗标准时间-UTC +03:30
ISTIndia Standard Time印度标准时间-UTC +05:30
ISTIrish Standard Time爱尔兰标准时间夏令时UTC +01:00
ISTIsrael Standard Time以色列标准时间-UTC +02:00
JSTJapan Standard Time日本标准时间-UTC +09:00
KOSTKosrae Time科斯雷时间-UTC +11:00
KSTKorea Standard Time韩国标准时间-UTC +08:30
LINTLine Islands Time莱恩群岛时间-UTC +14:00
MDTMountain Daylight Time山区夏令时夏令时UTC -06:00
MHTMarshall Islands Time马绍尔群岛时间-UTC +12:00
MSKMoscow Standard Time莫斯科标准时间-UTC +03:00
MSTMountain Standard Time山地标准时间-UTC -07:00
MYTMalaysia Time马来西亚时间-UTC +08:00
NDTNewfoundland Daylight Time纽芬兰夏令时夏令时UTC -02:30
NPTNepal Time尼泊尔时间-UTC +05:45
NSTNewfoundland Standard Time纽芬兰标准时间-UTC -03:30
NUTNiue Time纽埃时间-UTC -11:00
NZDTNew Zealand Daylight Time新西兰夏令时夏令时UTC +13:00
NZSTNew Zealand Standard Time新西兰标准时间-UTC +12:00
PDTPacific Daylight Time太平洋夏令时夏令时UTC -07:00
PETPeru Time秘鲁时间-UTC -05:00
PGTPapua New Guinea Time巴布亚新几内亚时间-UTC +10:00
PHTPhilippine Time菲律宾时间-UTC +08:00
PKTPakistan Standard Time巴基斯坦标准时间-UTC +05:00
PONTPohnpei Standard Time波纳佩标准时间-UTC +11:00
PSTPacific Standard Time太平洋标准时间-UTC -08:00
SASTSouth Africa Standard Time南非标准时间-UTC +02:00
SBTSolomon Islands Time所罗门群岛时间-UTC +11:00
SGTSingapore Time新加坡时间-UTC +08:00
SRTSuriname Time苏里南时间-UTC -03:00
SSTSamoa Standard Time萨摩亚标准时间-UTC -11:00
TAHTTahiti Time塔希提岛时间-UTC -10:00
TLTEast Timor Time东帝汶时间-UTC +09:00
TVTTuvalu Time图瓦卢时间-UTC +12:00
ULASTUlaanbaatar Summer Time乌兰巴托夏令时夏令时UTC +09:00
ULATUlaanbaatar Time乌兰巴托时间-UTC +08:00
UYSTUruguay Summer Time乌拉圭夏令时夏令时UTC -02:00
UYTUruguay Time乌拉圭时间-UTC -03:00
VETVenezuelan Standard Time委内瑞拉标准时间-UTC -04:00
WASTWest Africa Summer Time西非夏令时夏令时UTC +02:00
WATWest Africa Time西非时间-UTC +01:00
WESTWestern European Summer Time西欧夏令时间夏令时UTC +01:00
WETWestern European Time西欧时间-UTC -00:00
WIBWestern Indonesian Time印尼西部时间-UTC +07:00
WITEastern Indonesian Time印度尼西亚东部时间-UTC +09:00
WITACentral 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.02021-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。

搞不动了。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值