这可能是因为手机的默认语言不是英语,而您输入的月份名称是 (Oct
)。
解决方法是明确使用英语语言环境:
SimpleDateFormat dtfmt = new SimpleDateFormat("dd MMM yyyy hh:mm a", Locale.ENGLISH);
Date dt = dtfmt.parse("24 Oct 2016 7:31 pm");
不要直接使用SimpleDateFormat
(因为这个旧API存在很多问题和设计问题),您可以使用ThreeTen Backport,这是Java 8新日期/时间类的一个很好的后移。要在Android中使用它,您还需要ThreeTenABP(有关如何使用它的更多信息在这里)。
要使用的主要类是org.threeten.bp.LocalDateTime
(似乎是最好的选择,因为输入中有日期和时间字段)和org.threeten.bp.format.DateTimeFormatter
(用于解析输入)。我还使用java.util.Locale
类来确保它以英语解析月份名称,并使用org.threeten.bp.format.DateTimeFormatterBuilder
以确保它解析pm
(将其设置为不区分大小写,因为默认值为PM
):
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern("dd MMM yyyy h:mm a")
.toFormatter(Locale.ENGLISH);
LocalDateTime dt = LocalDateTime.parse("24 Oct 2016 7:31 pm", fmt);
System.out.println(dt);
输出结果将是:
2016-10-24T19:31
如果您需要将其转换为
java.util.Date
,可以使用
org.threeten.bp.DateTimeUtils
类。但您还需要知道将用于转换的时区。在下面的示例中,我使用的是“UTC”:
Date date = DateTimeUtils.toDate(dt.atZone(ZoneOffset.UTC).toInstant());
要切换到不同的时区,可以执行以下操作:
Date date = DateTimeUtils.toDate(dt.atZone(ZoneId.of("Europe/London")).toInstant());
请注意,API使用
IANA时区名称(始终采用格式
Continent/City
,如
America/Sao_Paulo
或
Europe/Berlin
)。避免使用三个字母的缩写(如
CST
或
PST
),因为它们是
模糊和不标准的。要找到最适合每个地区的时区,请使用
ZoneId.getAvailableZoneIds()
方法并检查哪个最适合您的用例。
附注:上述最后一个示例(
dt.atZone(ZoneId.of("Europe/London"))
)将在伦敦时区创建日期/时间
2016-10-24T19:31
。但如果您想在UTC中获得
2016-10-24T19:31
,然后将其转换到另一个时区,那么应该执行以下操作:
Date date = DateTimeUtils.toDate(dt
.toInstant(ZoneOffset.UTC)
.atZone(ZoneId.of("Europe/London")).toInstant());