That's because timezone's abbreviations such as IST are ambiguous. IST is used in India, Israel and Ireland, and SimpleDateFormat
assumes some of them as default, in obscure and undocumented ways (AFAIK). Actually, according to javadoc: "support of abbreviations is for JDK 1.1.x compatibility only and full names should be used".
One way to make it work is to arbitrarily choose a timezone and set it in the formatter:
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy hh:mm a z");
sdf.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));
Date date = sdf.parse("04/30/2018 06:00 PM IST");
Always use names in the format Continent/Region, such as Asia/Kolkata
. Those names are IANA's timezones names, and they are not ambiguous, so this make things work.
java.time API
If you're using Java 8 or higher, switch to the java.time API, which is much better. For Java 7 or lower, there's the Threeten Backport with the same classes and functionality.
In this API, you must set a list of all preferred timezones to be used in case of ambiguous names like IST:
// prefered zones
Set<ZoneId> preferredZones = new HashSet<>();
preferredZones.add(ZoneId.of("Asia/Kolkata"));
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
// date and time
.appendPattern("MM/dd/yyyy hh:mm a ")
// zone (use set of prefered zones)
.appendZoneText(TextStyle.SHORT, preferredZones)
// use English, because different locales can affect timezones names
.toFormatter(Locale.ENGLISH);
ZonedDateTime zdt = ZonedDateTime.parse("04/30/2018 06:00 PM IST", fmt);
If you still need to use java.util.Date
, it's easy to convert:
// Java 8
Date d = Date.from(zdt.toInstant());
// Java 7 (Threenten Backport)
Date d = DateTimeUtils.toDate(zdt.toInstant());