【转】Java 获取操作系统时区

 Java 可以通过 Timezone 获取时区,但是通过 Timezone 获取的时区是 JVM 初始化时保存的时区,并不是操作系统所设置的时区。当修改过操作系统的时区后,JVM 并不会同步更新。Timezone 获取时区的代码如下:

// 获取 JVM 启动时获取的时区
TimeZone.getDefault();
 
// 获取任意指定区域的时区
String[] zoneIDs = TimeZone.getAvailableIDs();
for(String zoneID: zoneIDs) {
    TimeZone.getTimeZone(zoneID);    
}

  当修改了操作系统的时区后,但JVM 并不会同步更新,因此直接通过 Timezone 获取默认时区并不是修改后的时区。若要程序获取修改后的操作系统时区,则可以这样修改:

// 将获取默认时区的两个前置条件设置为 false, 令其获取系统时间,原理见后面分析
synchronized (TimeZone.class) {
    TimeZone.setDefault(null);
    System.setProperty("user.timezone", "");
 
    TimeZone.getDefault();
}

这么做的原因是,我们需要调用Timezone 的本地方法 getSystemTimeZoneID(String javaHome),请看源码

    /**
     * Returns the reference to the default TimeZone object. This
     * method doesn't create a clone.
     */
    static TimeZone getDefaultRef() {
        TimeZone defaultZone = defaultTimeZone;
        if (defaultZone == null) {
            // Need to initialize the default time zone.
            defaultZone = setDefaultZone();
            assert defaultZone != null;
        }
        // Don't clone here.
        return defaultZone;
    }
 
    private static synchronized TimeZone setDefaultZone() {
        TimeZone tz;
        // get the time zone ID from the system properties
        String zoneID = AccessController.doPrivileged(
                new GetPropertyAction("user.timezone"));
 
        // if the time zone ID is not set (yet), perform the
        // platform to Java time zone ID mapping.
        if (zoneID == null || zoneID.isEmpty()) {
            String javaHome = AccessController.doPrivileged(
                    new GetPropertyAction("java.home"));
            try {
                zoneID = getSystemTimeZoneID(javaHome);    // 重点,这个方法就是我们需要调用的,但是 Timezone 并没有对外提供接口访问该方法,因此只能将前置条件改为 false, 令程序调用该方法即可获取操作系统的时间。
                if (zoneID == null) {
                    zoneID = GMT_ID;
                }
            } catch (NullPointerException e) {
                zoneID = GMT_ID;
            }
        }
 
        // Get the time zone for zoneID. But not fall back to
        // "GMT" here.
        tz = getTimeZone(zoneID, false);
 
        if (tz == null) {
            // If the given zone ID is unknown in Java, try to
            // get the GMT-offset-based time zone ID,
            // a.k.a. custom time zone ID (e.g., "GMT-08:00").
            String gmtOffsetID = getSystemGMTOffsetID();
            if (gmtOffsetID != null) {
                zoneID = gmtOffsetID;
            }
            tz = getTimeZone(zoneID, true);
        }
        assert tz != null;
 
        final String id = zoneID;
        AccessController.doPrivileged(new PrivilegedAction<Void>() {
            @Override
                public Void run() {
                    System.setProperty("user.timezone", id);
                    return null;
                }
            });
 
        defaultTimeZone = tz;
        return tz;
    }

  

转自:https://blog.csdn.net/zhaoxj_2017/article/details/99676852

 

posted @ 2020-02-22 17:58  三笑的酒  阅读(1391)  评论(0编辑  收藏  举报