Java SimpleDateFormat.getTimeZone (). GetID () returns Asia / Jerusalem instead of Asia / Kolkata

SimpleDateFormat getTimeZone().getID()

method returns Asia / Jerusalem instead of Asia / Kolkata for a date with the format EEE MMM dd HH:mm:ss z yyyy

. In fact, in my development machine, it returns Asia / Calcutta as expected. But in some other machine (production environment), it returns Asia / Jerusalem instead of Asia / Calcutta. Any idea what is causing this and how to solve it. The source code is shown below:

String input = "Mon Jun 12 13:29:47 IST 2017";
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");          
sdf.parse(input);
TimeZone timeZone = sdf.getTimeZone();
System.out.println(timeZone.getID());

      

+3


source to share


1 answer


Any idea what is causing this ...

Its a well-known problem with three and four letter acronyms. The third interpretation of IST is Irish Standard Time (Europe / Dublin). I don't know exactly what makes one JVM prefer one interpretation over the other. In at least one case, I have seen him prefer the default timezone setting for other interpretations. So if your development machine has Asia / Kolkata timezone settings, but your production machine does not, that would probably be the explanation. However, I would not rely on this as a reliable fact, and would also like to write robust enough code to work on computers and JVMs with different timezone settings.

... and how to solve it.

The perfect solution. Avoid getting a date and time string with a three or four letter abbreviation in the time zone. Prefer a zone offset from UTC and / or a time zone name in the form of a continent / city. I admit that this is not always possible.

Given your input string, since SimpleDateFormat

both TimeZone

are deprecated and the modern Java datetime interface is much more programmer friendly, and you also tagged your question with a class ZonedDateTime

, part of the modern API, let's take a modern solution first:

    DateTimeFormatter dtf = new DateTimeFormatterBuilder()
            .appendPattern("EEE MMM dd HH:mm:ss ")
            .appendZoneText(TextStyle.SHORT, Collections.singleton(ZoneId.of("Asia/Kolkata")))
            .appendPattern(" uuuu")
            .toFormatter(Locale.ROOT);
    ZonedDateTime dateTime = ZonedDateTime.parse(input, dtf);
    System.out.println(dateTime.getZone());

      

It prints:

Asia/Kolkata

      



The second argument I'm passing to appendZoneText()

is a set of preferred time zones. The documentation says: "The identified preferred zone id will be used if the painted texture zone name is not unique." Here's what we're doing here.

On my computer, I was also able to solve the problem in your code using deprecated classes. I inserted the following line before parsing.

    sdf.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));

      

However, the documentation of the older classes is more vague, so I would be less sure if this solution always works.

As an aside, and regardless of whether you are using old or modern classes, I recommend that you always specify the language for your parsing. "Mon" and "Jun" are in English, so parsing will not work on a machine with a non-linguistic setting if you do not specify a locale. Let me guess, your date string is not in English because it comes from the English language, but only because English is the universal language in the field of computing. If so, I consider it Locale.ROOT

appropriate. I already use it in my code. To use it in yours, add it as an argument to the constructor:

    SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.ROOT);

      

Locale.ENGLISH

works like other English locales.

+2


source







All Articles