mysql数据库时间突然是12小时制_为什么存入mysql数据库中的timestamp,晚了13或14个小时...
#?為什么存入mysql數據庫中的timestamp,晚了13個小時
##?查看數據庫時區
```
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数据库时间突然是12小时制_为什么存入mysql数据库中的timestamp,晚了13或14个小时...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql丢失链接_MySQL远程连接丢
- 下一篇: mysql 5.5主从同步_MySQL5