在没有分隔符的情况下,解析基于周的年和基于周的年份失败

时间:2018-01-15 15:43:14

标签: java localdate

我正在尝试从没有任何分隔符字符串的字符串中解析基于周的年份和基于周的工作年份。例如。 “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();

1 个答案:

答案 0 :(得分:3)

This is a known bug which has been fixed for Java-9.


If you are still on Java-8 and cannot move to Java-9 then

  • you are either out of luck

  • or you can use a 3rd-party-library.

Joda-Time: (uses "x" for week-based-year)

DateTimeFormatter formatter =
    new DateTimeFormatterBuilder().appendPattern("xxxxww").toFormatter();
LocalDate joda = LocalDate.parse("201803", formatter);
System.out.println(joda); // 2018-01-15

A replacement for parseDefaulting() is not available.

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

The replacement for parseDefaulting() can be achieved if you set up the formatter not for the type CalendarWeek but the basic type PlainDate and use this general formatter method withDefault(...). Example:

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();