Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 timezone for Instant.EPOCH is incorrect

I have a linux machine, and its time zone is set as Asia/Qatar. When I am printing Instant.EPOCH with formatter its giving me wrong zone information while for Instant.now() the zone information is correct. Below is my code and its output. Can anyone please help me, why is this discrepancy?

import java.util.Date;
import java.time.format.DateTimeFormatter;
import java.time.Instant;
import java.time.ZoneId;

public class DateTest {
   public static void main(String[] args) {
      String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS Z";
      Instant myInstant = Instant.EPOCH;
      Instant myInstantNow = Instant.now();
      DateTimeFormatter formatter =  DateTimeFormatter.ofPattern(pattern).withZone(ZoneId.systemDefault());
      System.out.println(formatter.format(myInstant));
      System.out.println(formatter.format(myInstantNow));
   }
}

The output of the code is:

1970-01-01T04:00:00.000 +0400
2019-09-29T18:30:14.766 +0300

Java version: "1.8.0_181"

Same code if I run in windows, its working fine. I am getting +0300 for Instant.EPOCH as well.

like image 300
Miracle Avatar asked Sep 29 '19 15:09

Miracle


People also ask

What TimeZone is instant Java?

The Instant class from Java Date Time API models a single instantaneous point on the timeline in UTC. This represents the count of nanoseconds since the epoch of the first moment of 1970 UTC.

Is instant now UTC?

An Instant by definition is in UTC.

How do I change the TimeZone in Java 8?

Typically, you get a TimeZone using getDefault which creates a TimeZone based on the time zone where the program is running. For example, for a program running in Japan, getDefault creates a TimeZone object based on Japanese Standard Time.

What is instant of epoch in Java?

The epoch-seconds are measured from the standard Java epoch of 1970-01-01T00:00:00Z where instants after the epoch have positive values, and earlier instants have negative values. For both the epoch-second and nanosecond parts, a larger value is always later on the time-line than a smaller value.


1 Answers

TL;DR: Your results from Linux are correct and as expected.

In 1970 Qatar was at offset +04:00 from GMT. The epoch is January 1, 1970. In 1972 Qatar changed from offset +04:00 to +03:00. Source: On Time Zone in Doha, Qatar (Ad Dawhah), in the Time zone changes for: dropdown select 1970–1979.

What went wrong on your Windows computer, then? It’s a guess on my part: The way I read Default Time Zones in the Windows documentation, Windows does not offer an Asia/Qatar time zone as a setting in Windows. So my guess is that your Windows is set to Arab Standard Time according to the table I just linked to, which in turn translates to UTC+03:00. Arab Standard Time (or Arabia Standard Time; abbreviated AST) is used in for example Kuwait, Iraq and Yemen too. But those countries have been on offset +03:00 all the time since 1970 and before. So when Java tries to pick up the default time zone from Windows, it could easily get a time zone with this history rather than the correct history for Qatar. As I said, it’s a guess for now. But you can easily verify. On your Windows computer try:

    System.out.println(ZoneId.systemDefault());

If it prints Asia/Qatar, my guess was wrong. If it prints something like GMT+03:00, I was right. If it prints something else, I may or may not be.

Edit: A couple of further links: AST – Arabia Standard Time (Standard Time) gives Kuwait as an example city. Time Changes in Kuwait City Over the Years infomrs us that Kuwait too has been on offset +03:00 since 1950.

Further edit: Thanks for confirming that Java on your Windows computer prints Asia/Riyadh as its default time zone. Riyadh, Saudi Arabia, has been on offset +03:00 since 1947. This at least partly explains why you get this offset even though it’s not correct for Qatar. Source

like image 61
Ole V.V. Avatar answered Sep 28 '22 02:09

Ole V.V.