It probably happens because the phone's default locale is not English, and the month name in your input is (Oct
).
The solution is to explicity use the English locale:
SimpleDateFormat dtfmt = new SimpleDateFormat("dd MMM yyyy hh:mm a", Locale.ENGLISH);
Date dt = dtfmt.parse("24 Oct 2016 7:31 pm");
Instead of directly working with SimpleDateFormat
(as this old API has lots of problems and design issues), you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. To use it in Android, you'll also need the ThreeTenABP (more on how to use it here).
The main classes to be used are org.threeten.bp.LocalDateTime
(it seems the best choice, as you have date and time fields in your input) and org.threeten.bp.format.DateTimeFormatter
(to parse the input). I also use java.util.Locale
class to make sure it parse the month names in English, and the org.threeten.bp.format.DateTimeFormatterBuilder
to make sure it parses pm
(make it case insensitive, as the default is PM
):
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
// case insensitive to parse "pm"
.parseCaseInsensitive()
// pattern
.appendPattern("dd MMM yyyy h:mm a")
// use English locale to parse month name (Oct)
.toFormatter(Locale.ENGLISH);
// parse input
LocalDateTime dt = LocalDateTime.parse("24 Oct 2016 7:31 pm", fmt);
System.out.println(dt); // 2016-10-24T19:31
The output will be:
2016-10-24T19:31
If you need to convert this to a java.util.Date
, you can use the org.threeten.bp.DateTimeUtils
class. But you also need to know what timezone will be used to convert this. In the example below, I'm using "UTC":
Date date = DateTimeUtils.toDate(dt.atZone(ZoneOffset.UTC).toInstant());
To change to a different zone, you can do:
Date date = DateTimeUtils.toDate(dt.atZone(ZoneId.of("Europe/London")).toInstant());
Note that the API uses IANA timezones names (always in the format Continent/City
, like America/Sao_Paulo
or Europe/Berlin
).
Avoid using the 3-letter abbreviations (like CST
or PST
) because they are ambiguous and not standard. To find the timezone that better suits each region, use the ZoneId.getAvailableZoneIds()
method and check which one fits best for your use cases.
PS: the last example above (dt.atZone(ZoneId.of("Europe/London"))
) will create the date/time 2016-10-24T19:31
in London timezone. But if what you want is 2016-10-24T19:31
in UTC, then convert it to another timezone, then you should do:
Date date = DateTimeUtils.toDate(dt
// first convert it to UTC
.toInstant(ZoneOffset.UTC)
// then convert to LondonTimezone
.atZone(ZoneId.of("Europe/London")).toInstant());