最近在開發中遇到一個很是罕見的問題,就是centos測試服務器上的時間雖然正確,可是安裝在上面的Tomacat7.x的時間時區出現錯誤。
個人程序代碼中,剛好使用了對時間查詢的sql語句,例如java
select <cols> from table where sendtime <= #{nowtime} and deadlinetime >= #{nowtime}
此時執行遠程單步調試,發現代碼中new Date()取得的當前時間nowtime,比正確的時間晚13個小時,形成查詢結果錯誤,難道取當前時間還會出錯?因而改用
mysql
Calendar calendar = Calendar.getInstance(); Date nowDate = calendar.getTime();
仍然不能得到正確的當前時間。這是怎麼回事,好長時間讓我一頭霧水。
在網上搜索了一下經過代碼解決的方案,有些文章給出了在代碼中設置時區的辦法,相似下面:
web
//更改當前時區爲東八區GMT+8,即北京時間。 TimeZone.setDefault(TimeZone.getTimeZone("GMT+8"));
這樣的話,經過new Date()或者calendar.getTime()能夠取得當前正確時間了,可是又出現了新的問題,mysql數據庫裏數據的時間字段的時間發生了改變,所有自動加了13個小時!
具體就是,用客戶端軟件鏈接到mysql,執行select <cols> from table order by sendtime desc相似的語句,看到sendtime,deadlinetime等字段的值沒有變化,可是遠程單步調試時,查看執行上面sql語句取出的結果集列表裏的時間,則所有自動日後推了13個小時,怎麼會這樣!前面忘記說了,時間字段都是timestamp型的字段。
看來使用代碼設置時區,會對數據庫的timestamp時間類型的字段產生影響。
至此,幾乎束手無策,機關用盡了。
忽然,眼前靈光一閃,有了一個突破口,想起這幾天觀察這個Tomcat7.x的log日誌文件的時間,也老是比當前正確時間晚13小時。是怎麼發現這個問題的呢?在centos測試機上tail -f catalina.out文件時,發現實時打印的帶時間信息的log語句,都比當前服務器時間晚13個小時。
筆者開發Java好多年,從未遇到過這種問題,之前遇到的,基本是服務器時區不正確,形成Tomcat等webserver時間跟着出錯,這樣至少服務器時區時間和webserver的時間仍是一致的;而此次的狀況,倒是服務器時區,時間都正確,Tomcat容器的時間/時區卻不正確。
至今尚不知如何形成這個錯誤的。由於我在本身帳號的目錄下直接wget一個tomcat7.x發行版並解壓安裝,並未出現這個問題,說明並非tomcat7.x自身的問題。顯然仍是在對tomcat7.x的某些配置作了修訂以後纔會引起這個問題。
這下問題明瞭了,先把log日誌的時間改正確再說!
爲了解決此問題,google了一些文章,在${catalina_home}/bin/catalina.sh文件中的JAVA_OPTS啓動參數中作了如下調整,
sql
JAVA_OPTS="-server -Duser.timezone=GMT+08 -Xms1024m -Xmx1024m"
即增長了時區選項-Duser.timezone=GMT+08,從新啓動Tomcat,log日誌的時間正確了。
接着,改回原始的代碼,註釋TimeZone.setDefault(TimeZone.getTimeZone("GMT+8"));等語句,全部的時間和sql查詢都正確了。
至此,問題完全解決。
數據庫