gpt4 book ai didi

java - 使用 Java 8 DateTimeFormatter 和西类牙月份名称进行解析

转载 作者:搜寻专家 更新时间:2023-11-01 01:31:43 25 4
gpt4 key购买 nike

使用“旧的”Java 8 之前的 SimpleDateFormat 我可以:

new java.text.SimpleDateFormat("MMM yyyy", new java.util.Locale("es", "ES")).parse("Mayo 2017")

获取具有西类牙月份名称的日期的 Date 对象。

如何使用 Java 8 和 DateTimeFormatter 实现同样的效果?

我试过:

DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).withLocale(new Locale("es", "ES")).ofPattern("MMM yyyy").parse("Mayo 2017")

但只得到一个java.time.format.DateTimeParseException

最佳答案

可以删除对 ofLocalizedDateTime() 的调用,因为最后您调用了 ofPattern(),创建了另一个具有完全不同模式的格式化程序(并返回了模式by ofLocalizedDateTime(FormatStyle.FULL)month year 非常不同,因此这并不是您真正想要的)。

另一个细节是 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 只是为它们使用一些默认值。在这种情况下,输入只有年和月,所以解析的 Date 将等同于解析的月/年,但日期将设置为 1,时间将设置为午夜(在 JVM 中默认时区)。

新的 API 对此非常严格,不会创建默认值,除非您告诉它这样做。配置它的一种方法是将 parseDefaultingjava.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());

默认时区 can be changed without notice, even at runtime ,因此最好始终明确说明您使用的是哪一个。

API 使用 IANA timezones names (始终采用 Region/City 格式,例如 America/New_YorkEurope/Berlin),因此您可以调用 ZoneId.of ("America/New_York") 例如。避免使用 3 个字母的缩写(如 CSTPST),因为它们是 ambiguous and not standard .

您可以通过调用 ZoneId.getAvailableZoneIds() 获取可用时区列表(并选择最适合您系统的时区)。

关于java - 使用 Java 8 DateTimeFormatter 和西类牙月份名称进行解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46305245/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com