【问题标题】:Parse week-based-year and week-of-week-based-year without separator character fails在没有分隔符的情况下解析基于周的年份和基于周的年份失败
【发布时间】:2018-06-24 06:36:51
【问题描述】:

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

【问题讨论】:

    标签: java localdate


    【解决方案1】:

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


    如果您仍在使用 Java-8 并且无法迁移到 Java-9,那么

    • 你要么不走运

    • 或者您可以使用第 3 方库。

    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 类型而是基本类型 PlainDate 并使用这种通用格式化程序方法 withDefault(...) 来实现。示例:

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

    【讨论】:

    • 当然,最简单的解决方法就是解析扩展的 ISO 表示法:input.substring(0, 4) + "-" + input.substring(4),但我将其排除在我的答案之外,因为我假设您正在寻找基于库的解决方案。
    • 非常感谢!很高兴知道这是一个错误。实际上我确实找到了一种解决方法(我编辑了我的问题以添加它)。
    • @fassen 很好,构建器方法也很好,因为它指示解析器仅解析 4 位数字,而不是更多。
    猜你喜欢
    • 2018-03-05
    • 1970-01-01
    • 1970-01-01
    • 2019-03-18
    • 2016-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-27
    相关资源
    最近更新 更多