Have you ever noticed that in some cases, Java will not take the time zone which is configured in a server? This has serious impacts if the server handles scheduling tasks and runs them periodically.
Before diving deep down, let’s understand what is a time zone?
Time Zones are geographical world globe division of 15 degree each, starting at Greenwich, England. It’s a uniform standard time for legal, commercial and social purposes.
While executing the below code, It will print the system time along with the timezone. I’ve added the output of the date command as well.
Even though the system timezone is configured as PST, java prints the timezone as GMT.
Set user.timezonein the command line as
Set the environmental variable
TZto provide the timezone.
The above solutions will work, but to understand and fix it once for all, read further for the actual fix. (All required source code links are embedded in the method names)
In the example java code, we call
new Date(). We know that java calls an object’s
.toString() method internally to provide the string representation of an object. Let’s take a look at the
toString method of the Date class in java.
The timezone on
Line:16 is set by calling the
date.getZone(). The variable
date is initialized by calling the normalize() method.
Now, let's break up and understand what the
It checks for the zone by checking the
user.timezoneproperty (which we didn’t set via the command line).
null, it gets the
java.homeproperty and calls the
getSystemTimeZoneID()which is a native method.
NULLvalues will set the timezone to default GMT. (So, this is why the timezone is set to GMT!)
Ignoring the unwanted details, let’s focus on what the findJavaTZ_md() does.
Now, we can understand why the quick search solutions mentioned to set values for
TZ! In our case, we didn’t set the TZ environmental variable which means
TZ = NULL.
It calls getPlatformTimeZoneID() if TZ is
NULL. (We’re about to reach a conclusion in the next step! Hang on..)
As the comment says, it will check for
/etc/timezone file which contains the system timezone information. I checked in my Ubuntu machine for the file and it's straightforward.
If the file is not present, it checks
/etc/localtime to obtain the timezone.
Here’s what happens in the above code.
Get the file status of
Check whether it's a symlink and read the symlink to obtain the timezone.
lstat to work as expected, it's required to have the executable(
x) permission on the file (as stated in the manpage of lstat). In my case, the /etc/localtime file doesn’t have the executable permission set. Hence, it returns NULL taking the default timezone of GMT.
If the file has the required permission set, the output will be like the below one. After resolving the symlink, the zone info will be taken using the getZoneNamemethod.
/etc/localtimefile is not a symlink, the
getPlatformTimeZoneID method will try to open and read the file like /etc/timezone. As the last fallback, it will recursively iterate the
/usr/share/zoneinfo directory to find the timezone. When none of them works out, the timezone is set to GMT- the default!
For my case, I just had to create a symlink of
After setting the symlink, running the
DateExampleprogram yields the expected result.
Thank you for reading!