当前位置: 首页 > 知识库问答 >
问题:

无法获取基于周的字符串从TemporalAccess的LocalDate

朱浩大
2023-03-14

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

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

下面是运行Java8(IBMJRE8.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);
}

正如在示例代码中看到的,我得到了不同的错误消息,尤其是第一个示例让我感到困惑,因为TemporalAccess包含基于周的年份、一年中的一周和一周天,这应该足以构建一个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

共有3个答案

晏卓君
2023-03-14

你可以使用YearMonth

public static void main(String[] args) {
    System.out.println(YearMonth.parse("201901", DateTimeFormatter.ofPattern("yyyyMM")));
}

输出

2019-01
艾茂学
2023-03-14

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

第二个是使用稍微奇怪的字段。如果你只是使用计时字段,你应该很好。您还可以调整模式,使其包含空格或破折号,因为解析似乎不喜欢将其包含在一个数字中——但不知道为什么

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

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。parseDefaulting-setep中的每周的第几天

陶鹏
2023-03-14

这适用于Java 8及更高版本:

    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .appendValue(WeekFields.ISO.weekBasedYear(), 4)
            .appendValue(WeekFields.ISO.weekOfWeekBasedYear(), 2)
            .parseDefaulting(WeekFields.ISO.dayOfWeek(), DayOfWeek.SUNDAY.getValue())
            .toFormatter();

    System.out.println(LocalDate.parse("201901", formatter));

输出为:

2019-01-06

我已经在Oracle Java 1.8.0_101上进行了测试。我还没有安装任何IBM Java。

使其工作的关键是使用weekOfWeekBasedYear()而不是weekOfYear()。我的其他变化是表面的<代码>WeekFields。ISO。weekOfYear()通过计算一年中的周一来定义周数,这不是您想要的,因为根据ISO,第一周可能在上一年年底(12月29日至31日)的某个周一开始。因此,它也不能很好地处理基于周的年份,Java拒绝将两者结合使用来标识周。

在Java 9上,您的formatter2()formatter3()也可以工作(在Oracle Java 9.0.4上测试)。Java 8中似乎存在一个bug,相邻字段解析在YYYYww中不起作用。不过,我已经搜索了Oracle Java错误数据库,但没有找到错误描述。

国际标准化组织8601标准规定了您使用的周的定义,也定义了一周的格式。它就像2012-W48。因此,除非你有一个很好的非常具体的理由不这样做,否则这是你应该使用的格式,尤其是在你与任何外部系统交换数据时。它还碰巧消除了Java8上的相邻字段解析问题。

    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .appendPattern("YYYY-'W'ww")
            .parseDefaulting(WeekFields.ISO.dayOfWeek(), DayOfWeek.SUNDAY.getValue())
            .toFormatter();

    System.out.println(LocalDate.parse("2019-W01", formatter));

2019-01-06

  • OracleJava错误数据
  • 维基百科文章:ISO 8601
 类似资料:
  • 我想像下面这样拆分这个字符串: {“我喜欢一个”、“橘子”、“以及”、“苹果”、“但主要是”、“苹果”、“苹果”,“苹果”,“橘子”,“是最好的水果。”} 在上面,我已经拆分了基于水果橙和苹果的字符串,但这两个水果也是子字符串列表的一部分。

  • 我无法打印已声明的字符串。以下是代码: 下面是错误:

  • Hello Support我无法从组件中获取字符串。我用两种方法做到了这一点,但结果很糟糕。 其结果是铸造错误 和 结果是文字上的“聊天。方括号”,这很奇怪。 请帮忙。谢谢

  • 问题内容: 我只想从字符串中获取数字。例如我有这样的事情 我只希望它打印出来 因此我可以将其乘以任何数字。 我试过了 我有 最好的方法是什么?我是菜鸟 问题答案: 您可以使用正则表达式: 要么

  • 我认为这是对当前运行的旋转器的简单复制/粘贴,只是将改为,但事实似乎并非如此。当我查找如何从旋转器中检索整数时,它看起来与我实现字符串旋转器的方式明显不同。我知道大多数事情都有不止一种方法,但我很好奇当使用旋转器时,是否有从字符串到整数的直接转换? 基本上,我如何使用相同的设置来实现整数的旋转器? Java方法: XML旋转器: 数组XML:

  • 我有两根绳子 在两种情况下,我应该删除