關于上一篇https://blog.csdn.net/u011165335/article/details/78924498
介紹了中國以及美國等的夏令時的特點:
*1.夏令時在結束的時間點是不會突變的
*2.通過代碼可以知道實際的夏令時時間段比 宣傳的少一個小時
系統時區在:注冊表
計算機\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\China Standard Time
先回顧一下之前的6個突變點:
環境jdk6
package
com.ysyimport java
.text.SimpleDateFormat
import java
.util.Date
import java
.util.Enumeration
import java
.util.Properties
import java
.util.TimeZoneimport org
.junit.Testpublic class Demo {// 比如
1986年的夏令時時間,從代碼來看,是從
1986-
05-
04 00:
00:
00到
1986-
09-
13 22:
59:
59@Testpublic void test4() throws Exception {SimpleDateFormat sf = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss")TimeZone
.setDefault(TimeZone
.getTimeZone(
"Asia/Shanghai"))TimeZone zone = TimeZone
.getDefault()System
.out.println(zone)Date d12 = sf
.parse(
"1986-05-03 23:59:00")Date d13 = sf
.parse(
"1986-05-04 00:00:00")Date d14 = sf
.parse(
"1986-06-04 00:00:00")Date d15 = sf
.parse(
"1986-09-13 22:59:59")Date d16 = sf
.parse(
"1986-09-13 23:00:00")Date d21 = sf
.parse(
"1987-04-11 23:59:00")Date d22 = sf
.parse(
"1987-04-12 00:00:00")Date d23 = sf
.parse(
"1987-09-12 22:59:59")Date d24 = sf
.parse(
"1987-09-12 23:00:00")Date d31 = sf
.parse(
"1988-04-09 23:59:59")Date d32 = sf
.parse(
"1988-04-10 00:00:00")Date d33 = sf
.parse(
"1988-09-10 22:59:59")Date d34 = sf
.parse(
"1988-09-10 23:00:00")System
.out.println(
"===============")Date d41 = sf
.parse(
"1989-04-15 23:59:59")Date d42 = sf
.parse(
"1989-04-16 00:00:00")Date d43 = sf
.parse(
"1989-09-16 22:59:59")Date d44 = sf
.parse(
"1989-09-16 23:00:00")System
.out.println(
"===============")Date d51 = sf
.parse(
"1990-04-14 23:59:59")Date d52 = sf
.parse(
"1990-04-15 00:00:00")Date d53 = sf
.parse(
"1990-09-15 22:59:59")Date d54 = sf
.parse(
"1990-09-15 23:00:00")System
.out.println(
"===============")Date d61 = sf
.parse(
"1991-04-13 23:59:59")Date d62 = sf
.parse(
"1991-04-14 00:00:00")Date d63 = sf
.parse(
"1991-09-14 22:59:59")Date d64 = sf
.parse(
"1991-09-14 23:00:00")System
.out.println(
"=========1986=======")System
.out.println(
"目標時區是否使用了夏令時:" + isDaylight(zone, d12))System
.out.println(
"目標時區是否使用了夏令時:" + isDaylight(zone, d13))System
.out.println(
"目標時區是否使用了夏令時:" + isDaylight(zone, d14))System
.out.println(
"目標時區是否使用了夏令時:" + isDaylight(zone, d15))System
.out.println(
"目標時區是否使用了夏令時:" + isDaylight(zone, d16))System
.out.println(
"=========1987=======")System
.out.println(
"目標時區是否使用了夏令時:" + isDaylight(zone, d21))System
.out.println(
"目標時區是否使用了夏令時:" + isDaylight(zone, d22))System
.out.println(
"目標時區是否使用了夏令時:" + isDaylight(zone, d23))System
.out.println(
"目標時區是否使用了夏令時:" + isDaylight(zone, d24))System
.out.println(
"=========1988=======")System
.out.println(
"目標時區是否使用了夏令時:" + isDaylight(zone, d31))System
.out.println(
"目標時區是否使用了夏令時:" + isDaylight(zone, d32))System
.out.println(
"目標時區是否使用了夏令時:" + isDaylight(zone, d33))System
.out.println(
"目標時區是否使用了夏令時:" + isDaylight(zone, d34))System
.out.println(
"=========1989=======")System
.out.println(
"目標時區是否使用了夏令時:" + isDaylight(zone, d41))System
.out.println(
"目標時區是否使用了夏令時:" + isDaylight(zone, d42))System
.out.println(
"目標時區是否使用了夏令時:" + isDaylight(zone, d43))System
.out.println(
"目標時區是否使用了夏令時:" + isDaylight(zone, d44))System
.out.println(
"=========1990=======")System
.out.println(
"目標時區是否使用了夏令時:" + isDaylight(zone, d51))System
.out.println(
"目標時區是否使用了夏令時:" + isDaylight(zone, d52))System
.out.println(
"目標時區是否使用了夏令時:" + isDaylight(zone, d53))System
.out.println(
"目標時區是否使用了夏令時:" + isDaylight(zone, d54))System
.out.println(
"======1991==========")System
.out.println(
"目標時區是否使用了夏令時:" + isDaylight(zone, d61))System
.out.println(
"目標時區是否使用了夏令時:" + isDaylight(zone, d62))System
.out.println(
"目標時區是否使用了夏令時:" + isDaylight(zone, d63))System
.out.println(
"目標時區是否使用了夏令時:" + isDaylight(zone, d64))//
6個突變點如下,只在開始實行的時候變化System
.out.println(
"===1986-05-04 00:00:00實際時間=====" + sf
.parse(
"1986-05-04 00:00:00")
.toLocaleString())System
.out.println(
"===1987-04-12 00:00:00實際時間=====" + sf
.parse(
"1987-04-12 00:00:00")
.toLocaleString())System
.out.println(
"===1988-04-10 00:00:00實際時間=====" + sf
.parse(
"1988-04-10 00:00:00")
.toLocaleString())System
.out.println(
"===1989-04-16 00:00:00實際時間=====" + sf
.parse(
"1989-04-16 00:00:00")
.toLocaleString())System
.out.println(
"===1990-04-15 00:00:00實際時間=====" + sf
.parse(
"1990-04-15 00:00:00")
.toLocaleString())System
.out.println(
"===1991-04-14 00:00:00實際時間=====" + sf
.parse(
"1991-04-14 00:00:00")
.toLocaleString())}// 判斷是否在夏令時private boolean isDaylight(TimeZone zone, Date date) {// 正常邏輯是:時區使用了夏令時再判斷時間,這里因為中國取消了if (zone
.getID()
.equals(
"Asia/Shanghai")) {return zone
.inDaylightTime(date)}return zone
.useDaylightTime() && zone
.inDaylightTime(date)}}
可以知道,目前就6個時間點發生加1個小時的變化:
1986-05-04 00:00:00實際時間=====1986-5-4 1:00:00
1987-04-12 00:00:00實際時間=====1987-4-12 1:00:00
1988-04-10 00:00:00實際時間=====1988-4-10 1:00:00
1989-04-16 00:00:00實際時間=====1989-4-16 1:00:00
1990-04-15 00:00:00實際時間=====1990-4-15 1:00:00
1991-04-14 00:00:00實際時間=====1991-4-14 1:00:00
上面出現,這種情況,說明系統的時區是Asia/Shanghai
那么如果不讓時間變化?
java.util.TimeZone類中getDefault方法的源代碼顯示,它最終是會調用sun.util.calendar.ZoneInfo類的getTimeZone 方法。這個方法為需要的時間區域返回一個作為ID的String參數。這個默認的時間區域ID是從 user.timezone (system)屬性那里得到。如果user.timezone沒有定義,它就會嘗試從user.country和java.home (System)屬性來得到ID。 如果它沒有成功找到一個時間區域ID,它就會使用一個”fallback” 的GMT值。換句話說, 如果它沒有計算出你的時間區域ID,它將使用GMT作為你默認的時間區域。
win對應jre\lib\zi
所以最關鍵的是設置好user.timezone即可;
如何設置,可以通過jvm參數設置或者System.setProperty
查看user.timezone
System.out.println(System.getProperty(“user.timezone”));
在jdk6,7輸出的時區是空的;jdk8的user.timezone可以直接獲取到系統時區;
所以只要在jvm設置 -Duser.timezone=GMT+8就可以了;
但是如果有多臺服務器,一個設置了GMT+8,一個沒設置,還是原來的Asia/Shanghai;那么2臺機子的時間傳輸會發生時間的轉換;
下面說的是模擬這種轉換:
情況1:win系統的默認時區為Asia/Shanghai;
然后你設置了TimeZone.setDefault(TimeZone.getTimeZone(“GMT+8”));類似你在jvm設置了GMT+8
那么現在一個時間 比如1990-04-17 00:00:00 ,這個時間正處在夏令時時間;
當你設置了GMT+8時區后,它認為正確的顯示時間應該是減一個小時,即1990-04-16 23:00:00;
怎么證明?
你可以在截圖的里面,把VM參數該為: -Duser.timezone=Asia/Shanghai
然后設置TimeZone.setDefault(TimeZone.getTimeZone(“GMT+8”)),
即可以印證;
===在夏令時1986-05-18 00:00:00實際時間=====1986-5-17 23:00:00
===在夏令時1987-06-17 00:00:00實際時間=====1987-6-16 23:00:00
===在夏令時1988-07-14 00:00:00實際時間=====1988-7-13 23:00:00
===不在夏令時1988-09-11 00:00:00實際時間=====1988-9-11 0:00:00
同理情況2:如win系統的默認時區為GMT+8;
然后你設置了TimeZone.setDefault(TimeZone.getTimeZone(“Asia/Shanghai”));
那么現在一個時間,比如1990-04-17 00:00:00,這個時間對于GMT+8而言,沒有夏令時概念;
當你設置了Asia/Shanghai這個時區后,(相當于帶有夏令時的東八區),此時會加一個小時,因為對于Asia/Shanghai而言,剛好在夏令時時間內! 于是實際顯示為:1990-04-17 01:00:00;
這里代碼演示如下:
這里假設win系統的默認時區為GMT+
8
private void test() throws ParseException {SimpleDateFormat sf = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss")// TimeZone
.setDefault(TimeZone
.getTimeZone(
"Asia/Shanghai"))TimeZone
.setDefault(TimeZone
.getTimeZone(
"Asia/Shanghai"))TimeZone zone = TimeZone
.getDefault()System
.out.println(zone)// 夏令時開始時間System
.out.println(
"===1986-05-04 00:00:00實際時間=====" + sf
.parse(
"1986-05-04 00:00:00")
.toLocaleString())System
.out.println(
"===1987-04-12 00:00:00實際時間=====" + sf
.parse(
"1987-04-12 00:00:00")
.toLocaleString())System
.out.println(
"===1988-04-10 00:00:00實際時間=====" + sf
.parse(
"1988-04-10 00:00:00")
.toLocaleString())System
.out.println(
"===1989-04-16 00:00:00實際時間=====" + sf
.parse(
"1989-04-16 00:00:00")
.toLocaleString())System
.out.println(
"===1990-04-15 00:00:00實際時間=====" + sf
.parse(
"1990-04-15 00:00:00")
.toLocaleString())System
.out.println(
"===1991-04-14 00:00:00實際時間=====" + sf
.parse(
"1991-04-14 00:00:00")
.toLocaleString())// 夏令時結束時間System
.out.println(
"===1986-09-13 23:00:00實際時間=====" + sf
.parse(
"1986-09-13 23:00:00")
.toLocaleString())System
.out.println(
"===1987-09-12 23:00:00實際時間=====" + sf
.parse(
"1987-09-12 23:00:00")
.toLocaleString())System
.out.println(
"===1988-09-10 23:00:00實際時間=====" + sf
.parse(
"1988-09-10 23:00:00")
.toLocaleString())System
.out.println(
"===1989-09-16 23:00:00實際時間=====" + sf
.parse(
"1989-09-16 23:00:00")
.toLocaleString())System
.out.println(
"===1990-09-15 23:00:00實際時間=====" + sf
.parse(
"1990-09-15 23:00:00")
.toLocaleString())System
.out.println(
"===1991-09-14 23:00:00實際時間=====" + sf
.parse(
"1991-09-14 23:00:00")
.toLocaleString())上面是已知的夏令時開始和結束時間打印下面幾個時間:System
.out.println(
"===在夏令時1986-05-18 00:00:00實際時間=====" + sf
.parse(
"1986-05-18 00:00:00")
.toLocaleString())System
.out.println(
"===在夏令時1987-06-17 00:00:00實際時間=====" + sf
.parse(
"1987-06-17 00:00:00")
.toLocaleString())System
.out.println(
"===在夏令時1988-07-14 00:00:00實際時間=====" + sf
.parse(
"1988-07-14 00:00:00")
.toLocaleString())System
.out.println(
"===不在夏令時1988-09-11 00:00:00實際時間=====" + sf
.parse(
"1988-09-11 00:00:00")
.toLocaleString())}
可以發現:跟預測的一樣,在夏令時的加1,不在的不變
===在夏令時1986-05-18 00:00:00實際時間=====1986-5-18 1:00:00
===在夏令時1987-06-17 00:00:00實際時間=====1987-6-17 1:00:00
===在夏令時1988-07-14 00:00:00實際時間=====1988-7-14 1:00:00
===不在夏令時1988-09-11 00:00:00實際時間=====1988-9-11 0:00:00
情況3:如win系統的默認時區為GMT+8;
然后你設置了TimeZone.setDefault(TimeZone.getTimeZone(“GMT+8”));那么時區一致,時間不會變化;
上面演示的就是類似2臺機子時區不一致的情況;
jvm設置對機子的設置是可以直接修改user.timezone,沒問題的;
讓多臺機子保持統一就可以了;
如果是linux,也可以修改clock文件;
總結
以上是生活随笔為你收集整理的java 夏令时jvm设置问题的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。