Skip to main content

Timezone in JVM

·2 mins

I wrote a Scala code to get the current time. However, the output is different on the development server and docker.

import java.util.Calendar


On my development server, it outputs Sun Oct 18 18:01:01 CST 2020, but in docker, it print a UTC time.

I guess it related to the timezone setting and do a research, here is the result.

How Did JVM Detect Timezone #

All of the code can be found in this function: private static synchronized TimeZone setDefaultZone()

  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;

First, it will check whether JVM has user.timezone property. If not, it will call this native method getSystemTimeZoneID, it was implemented in java.base/share/native/libjava/TimeZone.c, and the main logic is in java.base/unix/native/libjava/TimeZone_md.c.

In Timezone_md.c, it will find timezone by following steps, it will return the timezone immediately once found.

  1. Find TZ environment.
  2. Read /etc/timezone.
  3. Read /etc/localtime. If it is a soft link(ex: /usr/share/zoneinfo/Asia/Shanghai), return timezone by path. Otherwise, compare the content with all files in /usr/share/zoneinfo, if found, return timezone.
  4. Return GMT as timezone.

How to Change Timezone #

The available timezone in Linux can be listed by this command: timedatectl list-timezones

Add JVM param #

You can add -Duser.timezone=Asia/Shanghai as JVM parameters.

Set TZ environment variable #

Add export TZ=Asia/Shanghai in .bashrc.

Change /etc/timezone #

Set its content to Asia/Shanghai

Change /etc/localtime #

Link it to /usr/share/zoneinfo/Asia/Shanghai

Change timezone manually in Java Program #

All of these methods should work

  • Add this line before get time: TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"))
  • Set JVM property by code System.setProperty("user.timezone", "Asia/Shanghai")
  • Set timezone manually in Calendar Calendar.getInstance(TimeZone.getTimeZone("Asia/Shanghai"))

Ref #

  1. How to Set the JVM Time Zone
  2. jvm linux 时区设置
  3. Java default timezone detection, revisited
  4. Java读取系统默认时区
  5. How to set a JVM TimeZone Properly