3

SimpleDateFormat's getTimeZone().getID() method returns Asia/Jerusalem instead of Asia/Kolkata for the date with format EEE MMM dd HH:mm:ss z yyyy. Actually in my development machine it returns Asia/Kolkata as expected. But in some other machine(production environment) it returns Asia/Jerusalem instead of Asia/Kolkata. Any idea what causes this and how to resolve it. Source code is given 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());
Gal Dreiman
  • 3,969
  • 2
  • 21
  • 40
saikamesh
  • 4,569
  • 11
  • 53
  • 93
  • 6
    Timezone abbreviations such as IST, EST, etc... are not unique. IST stands for both Israel Standard Time and India Standard Time. You should use a different method to represent the timezone in your timestamp. – Eran Jun 28 '17 at 07:52
  • 3
    It’s a well known problem with three and four letter time zone abbreviations. A third interpretation of IST is Irish Standard Time (Europe/Dublin). – Ole V.V. Jun 28 '17 at 09:09
  • Where can I find the list of time zone ids for the given time zone abbreviation. For example for the abbreviation IST the time zone ids are Asia/Jerusalem, Asia/Kolkata, Europe/Dublin. – saikamesh Jun 28 '17 at 19:09
  • It was a good idea to post the last comment as [a separate question](https://stackoverflow.com/questions/44811282/java-how-to-get-list-of-time-zone-id-s-for-the-given-time-zone-abbreviation). Let’s continue there. – Ole V.V. Jun 28 '17 at 20:51

1 Answers1

3

Any idea what causes this…

It’s a well known problem with three and four letter time zone abbreviations. A third interpretation of IST is Irish Standard Time (Europe/Dublin). I don’t know exactly what causes one JVM to prefer one interpretation over another. In at least one case I have seen it prefer its default time zone setting over other interpretations. So if your development machine has an Asia/Kolkata time zone setting and your production machine hasn’t, this would probably be the explanation. However, I would not rely on this as a sure fact, and also I would want to write code robust enough to run on computers and JVMs with different time zone settings.

…and how to resolve it.

Ideal solution: Avoid getting a date-time string with a three or four letter time zone abbreviation in it. Prefer a zone offset from UTC and/or a time zone name in the form continent/city. I acknowledge that this is not always possible.

Given your input string, since SimpleDateFormat and TimeZone are outdated and the modern Java date and time API is much more programmer friendly, and you have also tagged your question with the ZonedDateTime class, a part of the modern API, let’s take the 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 pass to appendZoneText() is a set of preferred time zones. In the documentation it says “The matched preferred zone id will be used if the textural zone name being parsed is not unique.” This is what we are after here.

On my computer I was also able to solve the issue within your code using the outdated classes. I inserted the following line before parsing.

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

However, the documentation of the old classes is vaguer, so I would be less assured that this solution always works.

As an aside and no matter if you use the old or the modern classes, I recommend you always give explicit locale to your parsing. “Mon” and “Jun” are in English, so parsing will not work on a computer with a non-English locale setting unless you specify a locale. Let me guess, your date string isn’t in English because it comes from an English-speaking locale, but just because English is the universal language in computing. If so, I consider Locale.ROOT appropriate. I am already using it in my code. To use it in yours, add it as argument to the constructor:

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

Locale.ENGLISH works to, as do other English-speaking locales.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • 1
    I always thought that IST was Irish Standard Time, but using a `DateTimeFormatter` with `z zzzz` pattern gives "IST Irish **Summer** Time" in the summer and ["GMT Greenwich Mean Time" in the winter](https://www.timeanddate.com/time/zone/ireland/dublin). But I also found that ["Irish **Standard** Time"](https://www.timeanddate.com/time/zones/ist-ireland) name is [used for the summer time](https://en.wikipedia.org/wiki/Time_in_Ireland) as well. So, both names are valid? We really need a standard (ISO/RFC/whatever) for this... –  Jun 28 '17 at 16:56
  • 1
    @Hugo I couldn’t help laughing, I hope you forgive. In a number of answers and comments I have quoted [List of time zone abbreviations](https://en.wikipedia.org/wiki/List_of_time_zone_abbreviations) for “Irish Standard Time”, though “Summer Time” clearly makes more sense given the usage. Ireland does use summer time (DST) and a standard time in winter, so this only makes the ambiguity even worse and goes to underline the point you and I are both making: the three letter abbreviations are ambiguous and non-standard and should be avoided. – Ole V.V. Jun 28 '17 at 17:47
  • 1
    I wonder why they call DST as "standard". Anyway, as both names are used, maybe none is wrong (although this is very confusing). And don't worry, I also laughed when found this. Until someone standardizes it, that's all we can do... –  Jun 28 '17 at 17:59
  • 1
    I think it’s too late to standardize, @Hugo. No one will give up their own long-standing interpretation at this point. “Avoid” is the way to go… – Ole V.V. Jun 28 '17 at 18:08