可以删除对ofLocalizedDateTime()的调用,因为最后你调用ofPattern(),创建另一个格式不同的格式化程序(由ofLocalizedDateTime(FormatStyle.FULL)返回的模式与月份非常不同,所以这是不是你真正想要的).
另一个细节是Mayo是完整的月份名称,因此模式必须是MMMM(check the javadoc以获取更多详细信息).此外,默认情况下,DateTimeFormatter仅接受小写名称(至少在我使用西班牙语语言环境进行的测试中),因此您必须将格式化程序设置为不区分大小写.
您可以使用java.time.format.DateTimeFormatterBuilder来实现:
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
// case insensitive
.parseCaseInsensitive()
// pattern with full month name (MMMM)
.appendPattern("MMMM yyyy")
// set locale
.toFormatter(new Locale("es", "ES"));
// now it works
fmt.parse("Mayo 2017");
或者,您可以直接将其解析为java.time.YearMonth对象,因为它似乎是这种情况的最佳选择(因为输入只有年和月):
YearMonth ym = YearMonth.parse("Mayo 2017", fmt);
System.out.println(ym); // 2017-05
默认值
当输入没有所有字段时,SimpleDateFormat只是为它们使用一些默认值.在这种情况下,输入只有年和月,因此解析的日期将等于解析的月/年,但是日期将设置为1,时间将设置为午夜(在JVM默认时区).
新API对此非常严格,除非您告诉它,否则不会创建默认值.配置它的一种方法是使用parseDefaulting和java.time.temporal.ChronoField:
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
// case insensitive
.parseCaseInsensitive()
// pattern with full month name (MMMM)
.appendPattern("MMMM yyyy")
// default value for day of month
.parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
// default value for hour
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
// default value for minute
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
// set locale
.toFormatter(new Locale("es", "ES"));
这样,您可以将其解析为LocalDateTime,并将缺少的字段分配给相应的默认值:
LocalDateTime dt = LocalDateTime.parse("Mayo 2017", fmt);
System.out.println(dt); // 2017-05-01T00:00
如果需要获取与SimpleDateFormat创建的值相同的java.util.Date,可以将此LocalDateTime转换为JVM默认时区,然后将其转换为Date:
Date javaUtilDate = Date.from(dt.atZone(ZoneId.systemDefault()).toInstant());
请注意,我必须明确使用JVM默认时区(ZoneId.systemDefault()),这是SimpleDateFormat所使用的.
另一种方法是手动设置YearMonth值中的值:
// in this case, the formatter doesn't need the default values
YearMonth ym = YearMonth.parse("Mayo 2017", fmt);
ZonedDateTime z = ym
// set day of month to 1
.atDay(1)
// midnight at JVM default timezone
.atStartOfDay(ZoneId.systemDefault());
Date javaUtilDate = date.from(z.toInstant());
API使用IANA timezones names(总是采用Region / City格式,如America / New_York或Europe / Berlin),因此您可以调用ZoneId.of(“America / New_York”).
避免使用3个字母的缩写(如CST或PST),因为它们是ambiguous and not standard.
您可以通过调用ZoneId.getAvailableZoneIds()获取可用时区列表(并选择最适合您系统的时区).