Java讀取系統默認時區

工做中,遇到一個Java讀取默認時區的問題,後來看了openjdk的源碼,大體整理一下過程java

public class Test {
    public void test(){
        TimeZone.getDefault();
    }
}

TimeZone.getDefault()會跳到下面代碼:linux

    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);
                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;
    }

若是沒有設置時區的話,會進入一個native方法app

zoneID = getSystemTimeZoneID(javaHome);

這個方法的實現,能夠參考ide

openjdk-8u40-src-b25-10_feb_2015\openjdk\jdk\src\share\native\java\util\TimeZone.c
JNIEXPORT jstring JNICALL
Java_java_util_TimeZone_getSystemTimeZoneID(JNIEnv *env, jclass ign,
                                            jstring java_home)
{
    const char *java_home_dir;
    char *javaTZ;
    jstring jstrJavaTZ = NULL;

    CHECK_NULL_RETURN(java_home, NULL);

    java_home_dir = JNU_GetStringPlatformChars(env, java_home, 0);
    CHECK_NULL_RETURN(java_home_dir, NULL);

    /*
     * Invoke platform dependent mapping function
     */
    javaTZ = findJavaTZ_md(java_home_dir);
    if (javaTZ != NULL) {
        jstrJavaTZ = JNU_NewStringPlatform(env, javaTZ);
        free((void *)javaTZ);
    }

    JNU_ReleaseStringPlatformChars(env, java_home, java_home_dir);
    return jstrJavaTZ;
}

主要看:函數

javaTZ = findJavaTZ_md(java_home_dir);

繼續參考,下面TimeZone_md.c文件,能夠知道find_JavaTZ_md方法的實現spa

openjdk-8u40-src-b25-10_feb_2015\openjdk\jdk\src\solaris\native\java\util\TimeZone_md.c
char *
findJavaTZ_md(const char *java_home_dir)
{
    char *tz;
    char *javatz = NULL;
    char *freetz = NULL;

    tz = getenv("TZ");

#if defined(__linux__) || defined(_ALLBSD_SOURCE)
    if (tz == NULL) {
#else
#if defined (__solaris__) || defined(_AIX)
    if (tz == NULL || *tz == '\0') {
#endif
#endif
        tz = getPlatformTimeZoneID();
        freetz = tz;
    }

    /*
     * Remove any preceding ':'
     */
    if (tz != NULL && *tz == ':') {
        tz++;
    }

#ifdef __solaris__
    if (tz != NULL && strcmp(tz, "localtime") == 0) {
        tz = getSolarisDefaultZoneID();
        freetz = tz;
    }
#endif

    if (tz != NULL) {
#ifdef __linux__
        /*
         * Ignore "posix/" prefix.
         */
        if (strncmp(tz, "posix/", 6) == 0) {
            tz += 6;
        }
#endif
        javatz = strdup(tz);
        if (freetz != NULL) {
            free((void *) freetz);
        }

#ifdef _AIX
        freetz = mapPlatformToJavaTimezone(java_home_dir, javatz);
        if (javatz != NULL) {
            free((void *) javatz);
        }
        javatz = freetz;
#endif
    }

    return javatz;
}

 

tz = getPlatformTimeZoneID(),這個函數內容,就不貼了,能夠本身看下,總計起來,在Linux系統上,大概過程爲如下幾步:code

1.先找「TZ」變量,沒有,到2,orm

2.讀/etc/timezone,沒有到3,blog

3.比較/etc/localtime文件與"/usr/share/zoneinfo目錄下全部時區文件,若是有一致的,就爲該時區,若是沒有,到4,get

4.默認爲標準GMT

 

若有不正確的地方,歡迎指正!

相關文章
相關標籤/搜索