Java與MySQL時間不一致問題解決
一、問題情況描述
有時會遇到這樣的問題:MySQL中datetime、timestamp類型的列,Java與MySQL時間不一致。
在Java的數(shù)據(jù)庫配置url參數(shù)后面加serverTimezone=GMT%2B8,問題就解決了,但具體是什么導(dǎo)致的這一問題呢?
其實,Java與MySQL時間不一致主要是因為:CST時區(qū)的混亂問題。
二、CST時區(qū)混亂
1. CST有四種含義
CST是一個混亂的時區(qū),它有四種含義:
美國標(biāo)準(zhǔn)時間 Central Standard Time (USA):UTC-06:00(或UTC-05:00)
- 夏令時:3月11日至11月7日,使用UTC-05:00
- 冬令時:11月8日至次年3月11日,使用UTC-06:00
澳大利亞標(biāo)準(zhǔn)時間 Central Standard Time (Australia):UTC+09:30
中國標(biāo)準(zhǔn)時 China Standard Time:UTC+08:00
古巴標(biāo)準(zhǔn)時 Cuba Standard Time:UTC-04:00
CST在Linux、MySQL、Java中的含義:
- 在Linux或MySQL中,CST表示的是:中國標(biāo)準(zhǔn)時間(UTC+08:00)
- 在Java中,CST表示的是:中央標(biāo)準(zhǔn)時間(美國標(biāo)準(zhǔn)時間)(UTC-05:00或UTC-06:00)
Java中CST時區(qū)的分析:
public static void main(String[] args) { // 完整時區(qū)ID與時區(qū)描述:一共628個 String[] ids = TimeZone.getAvailableIDs(); for (String id : ids) { // System.out.println(id+"\t"+TimeZone.getTimeZone(id).getDisplayName()); } // 系統(tǒng)默認(rèn)時區(qū) TimeZone defaultTimeZone = TimeZone.getDefault(); System.out.println("系統(tǒng)默認(rèn)時區(qū):"+defaultTimeZone.getID()+"\t"+defaultTimeZone.getDisplayName()); // 北京時區(qū) TimeZone bjTimeZone = TimeZone.getTimeZone("Asia/Shanghai"); System.out.println("北京時區(qū):"+bjTimeZone.getID()+"\t"+bjTimeZone.getDisplayName()); // 東京時區(qū) TimeZone djTimeZone = TimeZone.getTimeZone("Asia/Tokyo"); System.out.println("東京時區(qū):"+djTimeZone.getID()+"\t"+djTimeZone.getDisplayName()); // CST時區(qū) TimeZone cstTimeZone = ZoneInfo.getTimeZone("CST"); System.out.println("CST時區(qū):"+cstTimeZone.getID()+"\t"+cstTimeZone.getDisplayName()); Date date = new Date(0L); System.out.println("時間戳=0對應(yīng)系統(tǒng)時間:"+date.toString()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); sdf.setTimeZone(bjTimeZone);// 設(shè)置北京時區(qū) System.out.println("時間戳0對應(yīng)北京時間:" + sdf.format(date)); sdf.setTimeZone(djTimeZone);// 設(shè)置東京時區(qū) System.out.println("時間戳0對應(yīng)東京時間:" + sdf.format(date)); sdf.setTimeZone(cstTimeZone);// 設(shè)置CST時區(qū) System.out.println("時間戳0對應(yīng)CST時間:" + sdf.format(date)); }
控制臺輸出:
系統(tǒng)默認(rèn)時區(qū):Asia/Shanghai 中國標(biāo)準(zhǔn)時間
北京時區(qū):Asia/Shanghai 中國標(biāo)準(zhǔn)時間
東京時區(qū):Asia/Tokyo 日本標(biāo)準(zhǔn)時間
CST時區(qū):CST 中央標(biāo)準(zhǔn)時間
時間戳=0對應(yīng)系統(tǒng)時間:Thu Jan 01 08:00:00 CST 1970
時間戳0對應(yīng)北京時間:1970-01-01 08:00:00
時間戳0對應(yīng)東京時間:1970-01-01 09:00:00
時間戳0對應(yīng)CST時間:1969-12-31 18:00:00
由輸出可知:
CST在Java中(TimeZone中的CST)表示的是中央標(biāo)準(zhǔn)時間(美國標(biāo)準(zhǔn)時間)
但需注意:Date中的CST是表示的中國標(biāo)準(zhǔn)時間
時間戳永遠(yuǎn)指的是UTC/GMT的值,同一時間戳在不同時區(qū)表示不同的絕對時間
中國的時區(qū)ID為Asia/Shanghai。
2. 什么是時區(qū)
為了照顧到各地區(qū)的使用方便,又使其他地方的人容易將本地的時間換算到別的地方時間上去。有關(guān)國際會議決定將地球表面按經(jīng)線從南到北,劃成24個區(qū)域,并且規(guī)定相鄰區(qū)域的時間相差1小時。
但由于國家常常是跨越多個時區(qū)的,為了照顧到行政上的方便,所以通常國家都會定義一個統(tǒng)一標(biāo)準(zhǔn)際的時區(qū)來使用,如中國就是統(tǒng)一使用東八區(qū)時間標(biāo)準(zhǔn)(北京時間)。
因為時區(qū)眾多,所以需要一個標(biāo)準(zhǔn)時間作為基準(zhǔn):
- 早期基準(zhǔn)是:GMT(格林尼治標(biāo)準(zhǔn)時間)
- 后來基準(zhǔn)是:UTC(協(xié)調(diào)世界時)
由于地球在它的橢圓軌道里的運(yùn)動速度不均勻,這個時刻可能和實際的太陽時相差16分鐘,地球每天的自轉(zhuǎn)是有些不規(guī)則的,而且正在緩慢減速。所以,GMT(格林尼治標(biāo)準(zhǔn)時間)已經(jīng)不再適合被作為標(biāo)準(zhǔn)時間使用。而是UTC(協(xié)調(diào)世界時)是原子時秒長為基礎(chǔ),更合適。UTC在時刻上盡量接近于GMT,這兩者幾乎是一樣的。
UTC這套時間系統(tǒng)被應(yīng)用于許多互聯(lián)網(wǎng)和萬維網(wǎng)的標(biāo)準(zhǔn)中,例如,網(wǎng)絡(luò)時間協(xié)議就是協(xié)調(diào)世界時在互聯(lián)網(wǎng)中使用的一種方式。
- 如果本地時間比UTC時間快,例如中國大陸的時間比UTC快8小時,寫作UTC+8(東8區(qū))。
- 如果本地時間比UTC時間慢,例如夏威夷的時間比UTC時間慢10小時,寫作UTC-10(西10區(qū))。
三、絕對時間與本地時間
絕對時間與本地時間關(guān)系:絕對時間 = 本地時間 & 時區(qū)偏移量 (AbsoluteTime = LocalDateTime & Offset)
1. 絕對時間
絕對時間(AbsoluteTime)是一個指向絕對時間線上的一個確定的時刻,不受所在地的影響。
UTC時間就是一個絕對時間。
當(dāng)我們記錄一個時間為1970-01-01T00:00:00Z(UTC描述時間的標(biāo)準(zhǔn)格式)時,這個時間的定義是沒有任何歧義的,在地球上的任何地方,他們的UTC時間也一定是相同的。
Unix時間戳也是一個絕對時間。
Unix時間戳的定義與時區(qū)無關(guān)。時間戳是指從絕對時間點(UTC時間1970年1月1日午夜)起經(jīng)過的秒數(shù)(或毫秒)。無論您使用什么時區(qū),時間戳都代表一個時刻,在任何地方都是相同的。
2. 本地時間
本地時間(LocalDateTime)是某一時區(qū)的時間。
舉例:北京時間2022-10-10 08:00:00。
- “2022-10-10 08:00:00”是本地時間(不含時區(qū)描述)
- “北京時間2022-10-10 08:00:00”整體是絕對時間(含時區(qū)描述)
3. 時區(qū)偏移量
全球分為24個時區(qū),每個時區(qū)和零時區(qū)相差了數(shù)個小時,也就是這里所說的時區(qū)偏移量(Offset)。
例如:北京時間2022-10-10 08:00:00,它本身是一個絕對時間,表示成UTC時間是2020-08-24T03:00:00+08:00
- 其中的2020-08-24T03:00:00是本地時間
- 其中的+08:00可以看作是時區(qū)偏移量
時區(qū)偏移量 = 地區(qū) & 規(guī)則 (Offset = Zone & Rules)
這里的規(guī)則(Rules)可能是一個變化的值,如果我們單純地認(rèn)為中國的時區(qū)偏移量是8個小時,就出錯了。
舉例說明:
中國其實也實行過夏令時,(1992年之后中國已經(jīng)沒有再實行過夏令時了,所以大家對這個概念并不熟悉)。
- 當(dāng)實行夏令時,中國標(biāo)準(zhǔn)時間的時區(qū)偏移量就是+09:00
- 當(dāng)非夏令時,中國標(biāo)準(zhǔn)時間的時區(qū)偏移量就是+08:00
因此,一個地區(qū)的時區(qū)偏移量是多少,是由當(dāng)?shù)氐恼邲Q定的,可能會隨著季節(jié)而發(fā)生變化,這就是上面所說的規(guī)則。
四、MySQL服務(wù)端時區(qū)
MySQL時區(qū)相關(guān)參數(shù)有兩個:
- system_time_zone(系統(tǒng)時區(qū))
- time_zone(全局時區(qū)或當(dāng)前會話時區(qū))
1. system_time_zone(系統(tǒng)時區(qū))
在MySQL啟動時會檢查當(dāng)前系統(tǒng)的時區(qū)并根據(jù)系統(tǒng)時區(qū)設(shè)置全局參數(shù)system_time_zone的值。值可以為UTC、CST、WIB等,默認(rèn)值一般為CST,該值是只讀的。
2. time_zone(全局時區(qū)或當(dāng)前會話時區(qū))
全局時區(qū):mysql服務(wù)端使用的時區(qū),可以修改,默認(rèn)值SYSTEM
mysql> show global variables like "%time_zone%"; +------------------+--------+ | Variable_name | Value | +------------------+--------+ | system_time_zone | CST | | time_zone | SYSTEM | +------------------+--------+ 2 rows in set (0.00 sec) mysql> set global time_zone = '+9:00'; Query OK, 0 rows affected (0.00 sec) mysql> show global variables like "%time_zone%"; +------------------+--------+ | Variable_name | Value | +------------------+--------+ | system_time_zone | CST | | time_zone | +09:00 | +------------------+--------+ 2 rows in set (0.00 sec)
此時查到的time_zone為全局時區(qū)
mysql> flush privileges; Query OK, 0 rows affected (0.01 sec)
該命令使全局時區(qū)的修改立即生效,否則只有等mysql服務(wù)重啟才會生效。
會話時區(qū):當(dāng)前會話的時區(qū),默認(rèn)取全局時區(qū)的值,可以修改
mysql> show variables like "%time_zone%"; +------------------+--------+ | Variable_name | Value | +------------------+--------+ | system_time_zone | CST | | time_zone | SYSTEM | +------------------+--------+ 2 rows in set (0.00 sec) mysql> set time_zone = '+9:00'; Query OK, 0 rows affected (0.00 sec) mysql> show variables like "%time_zone%"; +------------------+--------+ | Variable_name | Value | +------------------+--------+ | system_time_zone | CST | | time_zone | +09:00 | +------------------+--------+ 2 rows in set (0.00 sec)
此時查到的time_zone為當(dāng)前會話時區(qū)
五、問題具體分析
本文使用的MySQL驅(qū)動為cj驅(qū)動。
Java通過MySQL的jdbc驅(qū)動連接MySQL服務(wù)端:
- 通過jdbc的serverTimezone參數(shù)設(shè)置數(shù)據(jù)庫連接的時區(qū)。
- 當(dāng)未設(shè)置serverTimezone時,數(shù)據(jù)庫將連接使用MySQL服務(wù)端的time_zone(全局時區(qū)),默認(rèn)值為CST。time_zone的默認(rèn)值為SYSTEM,而SYSTEM取的是system_time_zone(系統(tǒng)時區(qū))的值,system_time_zone的默認(rèn)值就是CST。
對于CST,文章上文有提過:
- MySQL中,CST表示的是:中國標(biāo)準(zhǔn)時間(UTC+08:00)
- Java中,CST表示的是:美國標(biāo)準(zhǔn)時間(UTC-05:00或UTC-06:00)
由于Java和MySQL服務(wù)端對CST時區(qū)的不同解讀,最終導(dǎo)致了Java與MySQL時間不一致的問題。
關(guān)于serverTimezone
分析mysql的jdbc驅(qū)動代碼。MySQL驅(qū)動創(chuàng)建數(shù)據(jù)庫連接后,會配置此連接的時區(qū):
- 普通驅(qū)動:使用com.mysql.jdbc.ConnectionImpl#configureTimezone()配置連接的時區(qū)
- cj驅(qū)動:使用com.mysql.cj.protocol.a.NativeProtocol#configureTimezone()配置連接的時區(qū)
數(shù)據(jù)庫連接時區(qū)的設(shè)置:
- 如果配置了serverTimezone,則會使用serverTimezone配置的時區(qū)
- 如果沒配置,會去取數(shù)據(jù)庫中time_zone變量所配置的時區(qū)
serverTimezone配置的注意事項:
- 如果未配置serverTimezone,且數(shù)據(jù)庫time_zone是CST,時間會不一致
- 如果未配置serverTimezone,但數(shù)據(jù)庫time_zone不是CST(如GMT),時間一致
- 如果配置了serverTimezone,但與數(shù)據(jù)庫time_zone不是同一時區(qū),時間會不一致
- 如果配置了serverTimezone,且與數(shù)據(jù)庫time_zone是同一時區(qū),時間一致
你或許會發(fā)現(xiàn)一個奇怪的事情:貌似我配置的serverTimezone與據(jù)庫time_zone不是同一時區(qū)。但是Java中的存入時間和查詢得到的時間明明是一致且正確的,好像和上面描述得不一樣呀。
這里需要強(qiáng)調(diào)一下,上面所說的時間不一致是指的Java中的時間與MySQL數(shù)據(jù)庫中的時間(并不是Java中的存入時間和查詢得到的時間)。
為何Java中的存入時間和查詢得到的時間是一致且正確的?
舉個例子說明:
serverTimezone=+9(東九區(qū)),time_zone=+8:00(東八區(qū)),此時準(zhǔn)備把Java中的時間"2022-10-15 08:00:00"存入數(shù)據(jù)庫
- Java存入到MySQL時,誤認(rèn)為MySQL數(shù)據(jù)庫的時區(qū)是東九區(qū),時間+1小時,MySQL最終得到時間為:2022-10-15 09:00:00
- MySQL返回給Java時,誤認(rèn)為MySQL返回的時間是東九區(qū)的時間,時間-1小時,Java最終得到的時間為:2022-10-15 08:00:00,和正確時間一致
Java到MySQL的過程,以及MySQL到Java的過程,時間的處理在MySQL JDBC驅(qū)動環(huán)節(jié)。
serverTimezone配置的歸納總結(jié):
- 如果數(shù)據(jù)庫time_zone是CST,請配置serverTimezone=%2B8(+08:00)
- 如果數(shù)據(jù)庫time_zone是GMT(或其它MySQL與Java解析結(jié)果一致的時區(qū)格式),可以不配置serverTimezone參數(shù)。但如果要配置,請配置與數(shù)據(jù)庫數(shù)據(jù)庫time_zone一致的時區(qū)
雖然配置的serverTimezone與數(shù)據(jù)庫數(shù)據(jù)庫time_zone時區(qū)不一致,Java寫入后查詢得到的時間也是正常的,但MySQL中存的時間已經(jīng)是錯誤的了。
時間戳與時區(qū)無關(guān)性
時間戳:指1970-01-01 00:00:00(GMT/UTC)起到當(dāng)前的毫秒數(shù)。與時區(qū)無關(guān),不同時區(qū)同一個時刻的時間戳是相同的。
- 當(dāng)UTC時區(qū)的時間為1970-01-01 00:00:00時,時間戳為0
- 此時UTC+8(東8區(qū))時區(qū)的時間為1970-01-01 08:00:00,時間戳也為0
- 此時UTC+9(東9區(qū))時區(qū)的時間為1970-01-01 09:00:00,時間戳也為0
public static void main(String[] args) { Date date = new Date(0L); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); sdf.setTimeZone(TimeZone.getTimeZone("UTC")); System.out.println("時間戳0對應(yīng)時間(UTC):"+sdf.format(date)); sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); System.out.println("時間戳0對應(yīng)時間(UTC+8):"+sdf.format(date)); sdf.setTimeZone(TimeZone.getTimeZone("Asia/Tokyo")); System.out.println("時間戳0對應(yīng)時間(UTC+9):"+sdf.format(date)); }
時間戳0對應(yīng)時間(UTC):1970-01-01 00:00:00
時間戳0對應(yīng)時間(UTC+8):1970-01-01 08:00:00
時間戳0對應(yīng)時間(UTC+9):1970-01-01 09:00:00
主要步驟流程圖分析
1. 正確情況流程圖
Java系統(tǒng)時區(qū):Asia/Shanghai(東8區(qū))
JDBC數(shù)據(jù)庫連接時區(qū):serverTimezone=+8
MySQL全局時區(qū):time_zone=+08:00
2. 錯誤情況流程圖
Java系統(tǒng)時區(qū):Asia/Shanghai(東8區(qū))
JDBC數(shù)據(jù)庫連接時區(qū):serverTimezone=-5
MySQL全局時區(qū):time_zone=+08:00
錯誤情況詳細(xì)分析
Java寫入時間到MySQL服務(wù)端環(huán)節(jié):
Java準(zhǔn)備寫入的時間為:2022-10-15 08:00:00(UTC+8)
JDBC先轉(zhuǎn)化得到Timestamp:2022-10-15 00:00:00(UTC)
注意:時間戳記錄的是UTC時區(qū)的值,與UTC+8時區(qū)的2022-10-15 08:00:00是同一時間
JDBC在將Timestamp格式化為UTC-5時區(qū)(serverTimezone=-5)的時間字符串:2022-10-14 19:00:00,將字符串傳給MySQL服務(wù)端
MySQL服務(wù)端認(rèn)為2022-10-14 19:00:00就是MySQL全局時區(qū)time_zone=+08:00(UTC+8)時區(qū)的時間,存入。
MySQL服務(wù)端返回時間給Java環(huán)節(jié):
MySQL服務(wù)端返回UTC+8時區(qū)的時間字符串:2022-10-14 19:00:00
JDBC誤認(rèn)為該時間是UTC-5時區(qū)(serverTimezone=-5)先將時間字符串轉(zhuǎn)為Timestamp:2022-10-15 00:00:00(UTC)
Java將Timestamp轉(zhuǎn)化為:2022-10-15 00:00:00(UTC+8)
主要步驟源碼分析
① JDBC配置MySQL服務(wù)時區(qū)
如果配置了serverTimezone,則會使用serverTimezone配置的時區(qū)
如果沒配置,會去取數(shù)據(jù)庫中time_zone變量所配置的時區(qū)
具體方法:NativeProtocol類的configureTimezone方法
public void configureTimezone() { String configuredTimeZoneOnServer = this.serverSession.getServerVariable("time_zone"); if ("SYSTEM".equalsIgnoreCase(configuredTimeZoneOnServer)) { configuredTimeZoneOnServer = this.serverSession.getServerVariable("system_time_zone"); } // 獲取serverTimezone配置的時區(qū)(PropertyKey.serverTimezone=serverTimezone) String canonicalTimezone = getPropertySet().getStringProperty(PropertyKey.serverTimezone).getValue(); if (configuredTimeZoneOnServer != null) { // 如果沒配置serverTimezone,獲取數(shù)據(jù)庫中time_zone變量的時區(qū) if (canonicalTimezone == null || StringUtils.isEmptyOrWhitespaceOnly(canonicalTimezone)) { try { canonicalTimezone = TimeUtil.getCanonicalTimezone(configuredTimeZoneOnServer, getExceptionInterceptor()); } catch (IllegalArgumentException iae) { throw ExceptionFactory.createException(WrongArgumentException.class, iae.getMessage(), getExceptionInterceptor()); } } } if (canonicalTimezone != null && canonicalTimezone.length() > 0) { // 設(shè)置服務(wù)時區(qū) this.serverSession.setServerTimeZone(TimeZone.getTimeZone(canonicalTimezone)); if (!canonicalTimezone.equalsIgnoreCase("GMT") && this.serverSession.getServerTimeZone().getID().equals("GMT")) { throw ExceptionFactory.createException(WrongArgumentException.class, Messages.getString("Connection.9", new Object[] { canonicalTimezone }), getExceptionInterceptor()); } } // 設(shè)置默認(rèn)時區(qū) this.serverSession.setDefaultTimeZone(this.serverSession.getServerTimeZone()); }
JDBC創(chuàng)建數(shù)據(jù)庫連接就是使用該時區(qū)。
如果沒配置serverTimezone,獲取數(shù)據(jù)庫中time_zone變量的時區(qū)為CST,就會有問題,因為在java中:TimeZone.getTimeZone("CST")
表示的是中央標(biāo)準(zhǔn)時間(美國標(biāo)準(zhǔn)時間)UTC-5(UTC-6)。
CST問題的源頭:
public SqlTimestampValueFactory(PropertySet pset, Calendar calendar, TimeZone tz) { super(pset); if (calendar != null) { this.cal = (Calendar) calendar.clone(); } else { this.cal = Calendar.getInstance(tz, Locale.US); this.cal.setLenient(false); } }
debug結(jié)果:
② Java寫入時間到MySQL服務(wù)端
ClientPreparedStatement類的setTimestamp方法
@Override public void setTimestamp(int parameterIndex, Timestamp x) throws java.sql.SQLException { synchronized (checkClosed().getConnectionMutex()) { ((PreparedQuery<?>) this.query).getQueryBindings().setTimestamp(getCoreParameterIndex(parameterIndex), x); } }
ClientPreparedQueryBindings類的setTimestamp方法
public void setTimestamp(int parameterIndex, Timestamp x, Calendar targetCalendar, int fractionalLength) { if (x == null) { setNull(parameterIndex); } else { x = (Timestamp) x.clone(); if (!this.session.getServerSession().getCapabilities().serverSupportsFracSecs() || !this.sendFractionalSeconds.getValue() && fractionalLength == 0) { x = TimeUtil.truncateFractionalSeconds(x); } if (fractionalLength < 0) { fractionalLength = 6; } x = TimeUtil.adjustTimestampNanosPrecision(x, fractionalLength, !this.session.getServerSession().isServerTruncatesFracSecs()); // 將時間戳格式化為字符串時間 // this.session.getServerSession().getDefaultTimeZone() 時區(qū)(未配置serverTimezone,且數(shù)據(jù)庫中time_zone變量的時區(qū)為CST時,這里就是CST時區(qū)) this.tsdf = TimeUtil.getSimpleDateFormat(this.tsdf, "''yyyy-MM-dd HH:mm:ss", targetCalendar, targetCalendar != null ? null : this.session.getServerSession().getDefaultTimeZone()); StringBuffer buf = new StringBuffer(); buf.append(this.tsdf.format(x)); if (this.session.getServerSession().getCapabilities().serverSupportsFracSecs()) { buf.append('.'); buf.append(TimeUtil.formatNanos(x.getNanos(), 6)); } buf.append('\''); setValue(parameterIndex, buf.toString(), MysqlType.TIMESTAMP); } }
將時間格式化為字符串時間(根據(jù)連接的時區(qū))。
③ MySQL服務(wù)端返回時間給Java
ResultSetImpl類的getTimestamp方法
public Timestamp getTimestamp(String columnName) throws SQLException { return getTimestamp(findColumn(columnName)); } public Timestamp getTimestamp(int columnIndex) throws SQLException { checkRowPos(); checkColumnBounds(columnIndex); return this.thisRow.getValue(columnIndex - 1, this.defaultTimestampValueFactory); }
SqlTimestampValueFactory類的localCreateFromTimestamp方法
public Timestamp localCreateFromTimestamp(InternalTimestamp its) { if (its.getYear() == 0 && its.getMonth() == 0 && its.getDay() == 0) { throw new DataReadException(Messages.getString("ResultSet.InvalidZeroDate")); } synchronized (this.cal) { try { // 這里就是關(guān)鍵環(huán)節(jié),this.cal是一個Calendar類,里面有時區(qū)信息(未配置serverTimezone,且數(shù)據(jù)庫中time_zone變量的時區(qū)為CST時,這里就是CST時區(qū)) this.cal.set(its.getYear(), its.getMonth() - 1, its.getDay(), its.getHours(), its.getMinutes(), its.getSeconds()); Timestamp ts = new Timestamp(this.cal.getTimeInMillis()); ts.setNanos(its.getNanos()); return ts; } catch (IllegalArgumentException e) { throw ExceptionFactory.createException(WrongArgumentException.class, e.getMessage(), e); } } }
到此這篇關(guān)于Java與MySQL時間不一致問題解決的文章就介紹到這了,更多相關(guān)Java與MySQL時間不一致內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java實現(xiàn)List反轉(zhuǎn)的方法總結(jié)
在Java中,反轉(zhuǎn)一個List意味著將其元素的順序顛倒,使得第一個元素變成最后一個,最后一個元素變成第一個,依此類推,這一操作在處理數(shù)據(jù)集合時非常有用,所以本文給大家總結(jié)了Java實現(xiàn)List反轉(zhuǎn)的方法,需要的朋友可以參考下2024-04-04Java Web 實現(xiàn)QQ登錄功能一個帳號同一時間只能一個人登錄
對于一個帳號在同一時間只能一個人登錄,下文給大家介紹的非常詳細(xì),對java web qq 登錄功能感興趣的朋友一起看看吧2016-11-11Java函數(shù)式編程之通過行為參數(shù)化傳遞代碼
行為參數(shù)化就是可以幫助你處理頻繁變更的需求的一種軟件開發(fā)模式,這篇文章將給大家詳細(xì)的介紹一下Java函數(shù)式編程之行為參數(shù)化傳遞代碼,感興趣的同學(xué)可以參考閱讀下2023-08-08Java實現(xiàn)矩陣加減乘除及轉(zhuǎn)制等運(yùn)算功能示例
這篇文章主要介紹了Java實現(xiàn)矩陣加減乘除及轉(zhuǎn)制等運(yùn)算功能,結(jié)合實例形式總結(jié)分析了java常見的矩陣運(yùn)算實現(xiàn)技巧,需要的朋友可以參考下2018-01-01線程池調(diào)用kafka發(fā)送消息產(chǎn)生的內(nèi)存泄漏問題排查解決
這篇文章主要為大家介紹了線程池調(diào)用kafka發(fā)送消息產(chǎn)生的內(nèi)存泄漏問題排查解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08Spring Cloud 中@FeignClient注解中的contextId屬性詳解
這篇文章主要介紹了Spring Cloud 中@FeignClient注解中的contextId屬性詳解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09