1. 程式人生 > >Tomcat7.x時區問題導致時間獲取不正確

Tomcat7.x時區問題導致時間獲取不正確

最近在開發中遇到一個非常罕見的問題,就是centos測試伺服器上的時間雖然正確,但是安裝在上面的Tomacat7.x的時間時區出現錯誤。
我的程式程式碼中,恰好使用了對時間查詢的sql語句,例如
select <cols> from table where sendtime <= #{nowtime} and deadlinetime >= #{nowtime}
此時執行遠端單步除錯,發現程式碼中new Date()取得的當前時間nowtime,比正確的時間晚13個小時,造成查詢結果錯誤,難道取當前時間還會出錯?於是改用
Calendar calendar = Calendar.getInstance();
Date nowDate = calendar.getTime();

仍然不能獲得正確的當前時間。這是怎麼回事,好長時間讓我一頭霧水。

在網上搜索了一下通過程式碼解決的方案,有些文章給出了在程式碼中設定時區的辦法,類似下面:
    //更改當前時區為東八區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啟動引數中做了以下調整,
JAVA_OPTS="-server  -Duser.timezone=GMT+08 -Xms1024m -Xmx1024m"
即增加了時區選項-Duser.timezone=GMT+08,重新啟動Tomcat,log日誌的時間正確了。
接著,改回原始的程式碼,註釋TimeZone.setDefault(TimeZone.getTimeZone("GMT+8"));等語句,所有的時間和sql查詢都正確了。
至此,問題徹底解決。