/** * Returns the reference to the default TimeZone object. This * method doesn't create a clone. */ static TimeZone getDefaultRef() { TimeZonedefaultZone= defaultTimeZone; if (defaultZone == null) { // Need to initialize the default time zone. defaultZone = setDefaultZone(); assert defaultZone != null; } // Don't clone here. return defaultZone; } privatestaticsynchronized TimeZone setDefaultZone() { TimeZone tz; // get the time zone ID from the system properties Propertiesprops= GetPropertyAction.privilegedGetProperties(); StringzoneID= props.getProperty("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()) { StringjavaHome= StaticProperty.javaHome(); try { zoneID = getSystemTimeZoneID(javaHome); 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"). StringgmtOffsetID= getSystemGMTOffsetID(); if (gmtOffsetID != null) { zoneID = gmtOffsetID; } tz = getTimeZone(zoneID, true); } assert tz != null;
defaultTimeZone = tz; return tz; } /** * Gets the platform defined TimeZone ID. **/ privatestaticnative String getSystemTimeZoneID(String javaHome);
可以看到获取默认时区的主要代码逻辑在setDefaultZone这个方法中:
先从user.timezone这个系统参数中获取时区设置
1 2 3 4
TimeZone tz; // get the time zone ID from the system properties Propertiesprops= GetPropertyAction.privilegedGetProperties(); StringzoneID= props.getProperty("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()) { StringjavaHome= StaticProperty.javaHome(); try { zoneID = getSystemTimeZoneID(javaHome); if (zoneID == null) { zoneID = GMT_ID; } } catch (NullPointerException e) { zoneID = GMT_ID; } }
如果获取到了系统的默认时区设置,但是无法转换成java的ZoneID,则fallback到GMT
1 2 3 4 5 6 7 8 9 10
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"). StringgmtOffsetID= getSystemGMTOffsetID(); if (gmtOffsetID != null) { zoneID = gmtOffsetID; } tz = getTimeZone(zoneID, true); }
if (tz != NULL) { /* Ignore preceding ':' */ if (*tz == ':') { tz++; } #if defined(__linux__) /* Ignore "posix/" prefix on Linux. */ if (strncmp(tz, "posix/", 6) == 0) { tz += 6; } #endif
#if defined(_AIX) /* On AIX do the platform to Java mapping. */ javatz = mapPlatformToJavaTimezone(java_home_dir, tz); if (freetz != NULL) { free((void *) freetz); } #else if (freetz == NULL) { /* strdup if we are still working on getenv result. */ javatz = strdup(tz); } elseif (freetz != tz) { /* strdup and free the old buffer, if we moved the pointer. */ javatz = strdup(tz); free((void *) freetz); } else { /* we are good if we already work on a freshly allocated buffer. */ javatz = tz; } #endif }
/* * Performs Linux specific mapping and returns a zone ID * if found. Otherwise, NULL is returned. */ staticchar * getPlatformTimeZoneID() { structstat64statbuf; char *tz = NULL; FILE *fp; int fd; char *buf; size_t size; int res;
#if defined(__linux__) /* * Try reading the /etc/timezone file for Debian distros. There's * no spec of the file format available. This parsing assumes that * there's one line of an Olson tzid followed by a '\n', no * leading or trailing spaces, no comments./etc/timezone */ if ((fp = fopen(ETC_TIMEZONE_FILE, "r")) != NULL) { char line[256];
/* * Next, try /etc/localtime to find the zone ID. */ RESTARTABLE(lstat64(DEFAULT_ZONEINFO_FILE, &statbuf), res); if (res == -1) { returnNULL; }
/* * If it's a symlink, get the link name and its zone ID part. (The * older versions of timeconfig created a symlink as described in * the Red Hat man page. It was changed in 1999 to create a copy * of a zoneinfo file. It's no longer possible to get the zone ID * from /etc/localtime.) */ if (S_ISLNK(statbuf.st_mode)) { char linkbuf[PATH_MAX+1]; int len;
if ((len = readlink(DEFAULT_ZONEINFO_FILE, linkbuf, sizeof(linkbuf)-1)) == -1) { jio_fprintf(stderr, (constchar *) "can't get a symlink of %s\n", DEFAULT_ZONEINFO_FILE); returnNULL; } linkbuf[len] = '\0'; removeDuplicateSlashes(linkbuf); collapse(linkbuf); tz = getZoneName(linkbuf); if (tz != NULL) { tz = strdup(tz); return tz; } }
/* * If it's a regular file, we need to find out the same zoneinfo file * that has been copied as /etc/localtime. * If initial symbolic link resolution failed, we should treat target * file as a regular file. */ RESTARTABLE(open(DEFAULT_ZONEINFO_FILE, O_RDONLY), fd); if (fd == -1) { returnNULL; }