【转】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