我正在尝试从没有任何分隔符的字符串中解析基于周的年和基于周的年。例如。 “201812”(2018年的第12周)。像这样:

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                                    .appendPattern("YYYYww")
                                    .parseDefaulting(WeekFields.ISO.dayOfWeek(), 1)
                                    .toFormatter();
LocalDate parse = LocalDate.parse("201803", formatter);

但这给了我:
java.time.format.DateTimeParseException: Text '201803' could not be parsed at index 0

如果我在字段之间添加空格,如下所示:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                                    .appendPattern("YYYY ww")
                                    .parseDefaulting(WeekFields.ISO.dayOfWeek(), 1)
                                    .toFormatter();
LocalDate parse = LocalDate.parse("2018 03", formatter);

它工作正常,结果:
2018-01-15

Is this another bug like this one?还是我缺少什么?

我发现的解决方法是构建自定义格式器:
DateTimeFormatter yearWeekPattern = new DateTimeFormatterBuilder().appendValue(IsoFields.WEEK_BASED_YEAR, 4)
    .appendValue(IsoFields.WEEK_OF_WEEK_BASED_YEAR, 2)
    .parseDefaulting(WeekFields.ISO.dayOfWeek(), 1)
    .toFormatter();
LocalDate.parse("201803", yearWeekPattern).atStartOfDay(ZoneId.systemDefault()).toInstant();

最佳答案

这是一个已知错误,已经是fixed for Java-9

如果您仍在使用Java-8,并且无法移至Java-9,则

  • 你要么不走运
  • 或您可以使用3rd-party-library。

  • Joda-Time:(使用“x”表示基于周的年份)
    DateTimeFormatter formatter =
        new DateTimeFormatterBuilder().appendPattern("xxxxww").toFormatter();
    LocalDate joda = LocalDate.parse("201803", formatter);
    System.out.println(joda); // 2018-01-15
    

    没有可用的parseDefaulting()替代品。

    Time4J (my lib):
    ChronoFormatter<CalendarWeek> f =
        ChronoFormatter.ofPattern(
            "YYYYww",
            PatternType.CLDR,
            Locale.ROOT,
            CalendarWeek.chronology()
        );
    CalendarWeek cw = f.parse("201803");
    java.time.LocalDate d = cw.at(Weekday.MONDAY).toTemporalAccessor();
    System.out.println(d); // 2018-01-15
    

    如果您不为parseDefaulting()类型而是基本类型CalendarWeek设置格式化程序,并使用此通用格式化程序方法withDefault(...),则可以实现PlainDate的替换。例子:
    ChronoFormatter<PlainDate> f =
        ChronoFormatter
            .ofDatePattern("YYYYww", PatternType.CLDR, Locale.ROOT)
            .withDefault(PlainDate.DAY_OF_WEEK, Weekday.MONDAY);
    PlainDate cw = f.parse("201803");
    java.time.LocalDate d = cw.toTemporalAccessor();
    

    10-08 18:13