-3

I have string date "Tue May 07 15:41:50 IST 2019" want to convert into date but its not working mention below formats.

SimpleDateFormat formatter = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy",Locale.US/Locale/English both);
SimpleDateFormat formatter = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");
SimpleDateFormat formatter = new SimpleDateFormat("EEE MMM dd HH:mm:ss ZZZ yyyy");
SimpleDateFormat formatter = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzzz yyyy");
date date = formatter.parse("Tue May 07 15:41:50 IST 2019");

When I am trying to parse IST using z or zzz or Z or ZZZ but not success in android.

Dale K
  • 25,246
  • 15
  • 42
  • 71

3 Answers3

1

Normally, using z would give you the correct timezone, here with HongKong :

System.out.println(
    new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy z", Locale.ENGLISH)
        .parse("Tue May 07 15:41:50 2019 HKT")
);

Tue May 07 09:41:50 CEST 2019

Documentation

But like it is explained in TimeZone, a "Three-letter time zone IDs" is not unique and this is the reason it should not be used.

[...] some other three-letter time zone IDs (such as "PST", "CTT", "AST") are also supported. However, their use is deprecated because the same abbreviation is often used for multiple time zones (for example, "CST" could be U.S. "Central Standard Time" and "China Standard Time"), and the Java platform can then only recognize one of them.

Proof of concept

We can check that IST represents more than one timezone with this dirty code to get every Timezone matching the ZoneId of every "IST" zone supported by the SimpleDateFormatter:

String shortZoneID = "IST";
Arrays.stream(
            new SimpleDateFormat().getDateFormatSymbols().getZoneStrings())
            .filter(s -> shortZoneID.equals(s[2]) || shortZoneID.equals(s[4]))
            .map(s -> TimeZone.getTimeZone(s[0]))
            .map(t -> String.format("%-50s %s", t.getDisplayName(), Duration.of(t.getRawOffset(), ChronoUnit.MILLIS)))
            .distinct()
            .forEach(System.out::println)
            ;

Output :

Israel Standard Time                               PT2H  
India Standard Time                                PT5H30M  
Greenwich Mean Time                                PT0S  

Explaining why IST" seems to be in GMT.

System.out.println(
    new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy z", Locale.ENGLISH)
        .parse("Tue May 07 15:41:50 2019 IST")
);

Tue May 07 15:41:50 CEST 2019

Not sure yet how Java prioritize the timezone in this case, does it take the first found, or is it based on the current locale (I am on GMT+01:00 timezone)?
But even with this information, the result might not be correct.

Solutions

In the meantime, here are some correct form of recovering a Timezone :

Using the offset

System.out.println(
        new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy XXX", Locale.ENGLISH)
            .parse("Tue May 07 15:41:50 2019 +05:30"));

Using the full name of the zone

System.out.println(
        new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy zzzz", Locale.ENGLISH)
            .parse("Tue May 07 15:41:50 2019 India Standard Time"));

Both output :

Tue May 07 12:11:50 CEST 2019

Community
  • 1
  • 1
AxelH
  • 14,325
  • 2
  • 25
  • 55
0
String dateString = "Tue May 07 15:41:50 IST 2019"  
SimpleDateFormat sdf = new SimpleDateFormat("EE MMM dd HH:mm:ss z yyyy");
Date date = sdf.parse(dateString);
System.out.println(date);
ViBe
  • 27
  • 1
  • 7
  • Since `new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy")` did not give the desired result for the OP, is there any reason to believe that your code would? – Ole V.V. Mar 07 '21 at 12:02
0

java.time

I recommend that you use java.time, the modern Java date and time API, for your date and time work.

Since IST is ambiguous (as very many three letter time zone abbreviations), you need to specify your preferred interpretation when parsing a string that contains this abbreviation. For ease of demonstration I am using this method (it’s probably not one that one would use for production):

static ZonedDateTime parseWithPreferredTimeZone(String input, ZoneId preferredZone) {
    DateTimeFormatter parser = new DateTimeFormatterBuilder()
            .appendPattern("EEE MMM dd HH:mm:ss ")
            .appendZoneText(TextStyle.SHORT, Collections.singleton(preferredZone))
            .appendPattern(" yyyy")
            .toFormatter(Locale.ENGLISH);
    return ZonedDateTime.parse(input, parser);
}

Now let’s see it in action:

    String stringToParse = "Tue May 07 15:41:50 IST 2019";
    
    System.out.println(parseWithPreferredTimeZone(stringToParse,
            ZoneId.of("Atlantic/Reykjavik")));
    System.out.println(parseWithPreferredTimeZone(stringToParse,
            ZoneId.of("Europe/Dublin")));
    System.out.println(parseWithPreferredTimeZone(stringToParse,
            ZoneId.of("Asia/Jerusalem")));
    System.out.println(parseWithPreferredTimeZone(stringToParse,
            ZoneId.of("Asia/Kolkata")));

Output on my Java 9 is:

2019-05-07T15:41:50Z[Atlantic/Reykjavik]
2019-05-07T15:41:50+01:00[Europe/Dublin]
2019-05-07T15:41:50+03:00[Asia/Jerusalem]
2019-05-07T15:41:50+05:30[Asia/Kolkata]

As you can see, you can get the interpretation that you want.

Question: Doesn’t java.time require Android API level 26?

java.time works nicely on both older and newer Android devices. It just requires at least Java 6.

  • In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
  • In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
  • On older Android either use desugaring or the Android edition of ThreeTen Backport. It’s called ThreeTenABP. In the latter case make sure you import the date and time classes from org.threeten.bp with subpackages.

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161