首页 > 解决方案 > 无法从 TemporalAccessor 获取基于周的字符串的 LocalDate

问题描述

我正在尝试将格式为“YYYYww”(例如 201901)的简单字符串解析为 LocalDate,但我的尝试都没有成功。

我试图通过简单地使用模式“YYYYww”以及手动将值附加到 FormatterBuilder 来解析它。由于我的输入字符串不包含一天,我还将格式化程序配置为默认为星期日。

这是运行 Java 8 (IBM JRE 8.0.5.25) 对我来说失败的代码。

public static void main(String[] args) {
    formatter1(); // Unable to obtain LocalDate from TemporalAccessor
    formatter2(); // Text '201901' could not be parsed at index 0
    formatter3(); // Text '201901' could not be parsed at index 6
}

public static void formatter1() {
    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .appendValue(WeekFields.ISO.weekBasedYear(), 4, 4, SignStyle.NEVER)
            .appendValue(WeekFields.ISO.weekOfYear(), 2, 2, SignStyle.NEVER)
            .parseDefaulting(WeekFields.ISO.dayOfWeek(), DayOfWeek.SUNDAY.getValue())
            .toFormatter();

    LocalDate.parse("201901", formatter);
}

public static void formatter2() {
    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .appendPattern("YYYYww")
            .parseDefaulting(WeekFields.ISO.dayOfWeek(), DayOfWeek.SUNDAY.getValue())
            .toFormatter();

    LocalDate.parse("201901", formatter);
}

public static void formatter3() {
    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .parseLenient()
            .appendPattern("YYYYww")
            .parseDefaulting(WeekFields.ISO.dayOfWeek(), DayOfWeek.SUNDAY.getValue())
            .toFormatter();

    LocalDate.parse("201901", formatter);
}

正如在示例代码中看到的,我收到不同的错误消息,尤其是第一个示例让我感到困惑,因为 TemporalAccessor 包含基于周的年份、一年中的星期和工作日,这应该足以构建 LocalDate .

Exception in thread "main" java.time.format.DateTimeParseException: Text '201901' could not be parsed: Unable to obtain LocalDate from TemporalAccessor: {WeekOfYear[WeekFields[MONDAY,4]]=1, WeekBasedYear[WeekFields[MONDAY,4]]=2019, DayOfWeek=7},ISO of type java.time.format.Parsed
    at java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:1931)
    at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1866)
    at java.time.LocalDate.parse(LocalDate.java:411)
    at Main.formatter1(Main.java:22)
    at Main.main(Main.java:10)
Caused by: java.time.DateTimeException: Unable to obtain LocalDate from TemporalAccessor: {WeekOfYear[WeekFields[MONDAY,4]]=1, WeekBasedYear[WeekFields[MONDAY,4]]=2019, DayOfWeek=7},ISO of type java.time.format.Parsed
    at java.time.LocalDate.from(LocalDate.java:379)
    at java.time.LocalDate$$Lambda$7.000000001061ED20.queryFrom(Unknown Source)
    at java.time.format.Parsed.query(Parsed.java:237)
    at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1862)
    ... 3 more

标签: javajava-time

解决方案


据我所知,你不能这样做。据我所知,您的代码存在两个问题。首先是 aLocalDate没有足够的信息,因为您的代码无法知道它应该解析到哪个工作日。

二是使用略显奇怪的字段。如果您只使用 Chrono 字段,您应该没问题。您也许还可以调整您的模式以包含空格或破折号,因为解析似乎不喜欢它在一个数字中 - 不知道为什么

例如,您可以执行以下操作:

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
        .appendValue(ChronoField.YEAR, 4, 4, SignStyle.NEVER)
        .appendValue(ChronoField.ALIGNED_WEEK_OF_YEAR, 2, 2, SignStyle.NEVER)
        .parseDefaulting(ChronoField.DAY_OF_WEEK, DayOfWeek.SUNDAY.getValue())
        .toFormatter();

LocalDate d = LocalDate.parse("201933", formatter);

但是,使用周数似乎不是一个好的选择。如果你能像@butiri-dan 建议的那样坚持几个月,你很可能会过得更好。

编辑:根据@carlos-heuberger 的建议,它现在ChronoField.DAY_OF_WEEKparseDefaulting-setep中使用


推荐阅读