本文講解如何在tomcat啟動時設置JVM默認時區。
環境:JDK1.8.114
web容器:Tomcat 9
tomcat啟動腳本 /etc/init.d/tomcat
操作系統ubuntu 16 amd64
作為java開發人員,以下代碼應該不會覺有有什么意外,運行正常。
是的,他的確能正常運行。
String sql = "insert into `order`(clientid,licensestr,type,amount,`status`,months,info,createtime) values(?,?,?,?,?,?,?,?)"; try { PreparedStatement pst = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS); pst.setLong(1, clientid); pst.setString(2, String.format("SN-%s",generateNextSequence())); pst.setInt(3, 1); pst.setInt(4, 1); pst.setString(5, "status/waitforlicense"); pst.setInt(6, -1); pst.setString(7, ""); SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); pst.setString(8, format.format(new Date())); int effect = pst.executeUpdate(); if(effect>0){ ResultSet rs = pst.getGeneratedKeys(); if(rs.next()) { long last_inserted_id = rs.getLong(1); return last_inserted_id; } } } catch (SQLException e) { e.printStackTrace(); }
他會在數據庫中插入的createtime是當前JVM的默認本地(Locale)時間。因為特殊需要,筆者曾經在非東八區時間(GMT+8) --北京時間 部署項目。
錄入數據庫的時間不是北京時間,當業務數據撈(load)上來的時候一頭霧水,也與業務數據時間不一致,產生了很多煩惱。
有的小伙伴會想到以下命令(不同版本的Ubuntu命令不一樣)
cp /usr/share/zoneinfo/Asia/ShangHai /etc/localtime 或 cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
筆者在本地虛擬機執行以上命令就能得到正確的時間,但是筆者購買的虛擬機環境已經設置了正確的時間,
Tomcat獲取的時間仍舊不對,后來筆者找到了類似(jdk1.8)代碼,替換以上的createtime字段,插入的數據也是對的。
ZoneId zoneId = ZoneId.of("GMT+8"); ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(Instant.now(), zoneId); System.out.println(zonedDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
以上這段代碼來自Stackoverflow:How to get local time of different time zones?
根據ZoneId.of的api說明,你還可以選擇其他更多格式,例如 America/New_York,Z,UTC+01:00,GMT,GMT-2,-4等,具體可以參考ZoneId API。
當前JVM更多時區獲取方法可以參考以下代碼:
String[] ids = TimeZone.getAvailableIDs(); for (String id : ids) { System.out.println(displayTimeZone(TimeZone.getTimeZone(id))); } private static String displayTimeZone(TimeZone tz) { long hours = TimeUnit.MILLISECONDS.toHours(tz.getRawOffset()); long minutes = TimeUnit.MILLISECONDS.toMinutes(tz.getRawOffset()) - TimeUnit.HOURS.toMinutes(hours); // avoid -4:-30 issue minutes = Math.abs(minutes); String result = ""; if (hours > 0) { result = String.format("(GMT+%d:%02d) %s", hours, minutes, tz.getID()); } else { result = String.format("(GMT%d:%02d) %s", hours, minutes, tz.getID()); } return result; }
有些特殊情況下是不允許修改代碼的,如沒有編譯環境,代碼閉源等。
這個時候我們就要從JVM入手了,一個tomcat進程對應一個JVM,我們可以對這個JVM設置一些啟動參數,帶着這個疑問我們找到了解決方法
windows下編輯tomcat/bin/setclasspath.bat 在所有代碼之前添加 set JAVA_OPTS="-Duser.timezone=GMT" linux編輯tomcat/bin/setclasspath.sh 在所有代碼之前添加 export JAVA_OPTS="-Duser.timezone=GMT" 如果設置了隨機啟動腳本要修改隨機啟動腳本 vim /etc/init.d/tomcat export JAVA_OPTS="-Duser.timezone=GMT+8:00" 或 export JAVA_OPTS="-Duser.timezone=GMT+8"
經過以上設置,不管你的程序放到什么地方,每次獲取的時間都是北京時間。