java.time.format.DateTimeParseException,不知道怎么解决

java.time.format.DateTimeParseException, and I do not know how to solve it

我正在尝试从 csv 文件中获取有关某些运动员的数据,然后创建将存储在列表中的运动员对象。 问题是当我尝试解析他们得到的时间时出现错误,因为 LocalDateTime.This 是我得到的错误:

线程“主”中的异常java.time.format.DateTimeParseException:文本“30:27”无法 被解析:无法从 TemporalAccessor 获取 LocalDateTime:{MinuteOfHour=30, MicroOfSecond=0, MilliOfSecond=0, SecondOfMinute=27, NanoOfSecond=0},ISO 类型 java.time.format.Parsed

这是代码:

public static void addAthletes() {
    try (BufferedReader br = new BufferedReader(
            new FileReader("C:\Users\****\******\**********\src\main\java\ro\sci\tema10_ski_biathlon_standings\standings.csv"))) {
        String line = null;
        while ((line = br.readLine()) != null) {
            athleteList.add(getAthleteFromCsvLine(line));
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

private static Athlete getAthleteFromCsvLine(String line) {

    String[] athleteAttributes = line.split(",");

    if (athleteAttributes.length != 7) {
        throw new IllegalArgumentException();
    }

    int athleteNumber = Integer.parseInt(athleteAttributes[0].trim());
    LocalDateTime skiTimeResults = LocalDateTime.parse(athleteAttributes[3].trim(),
            DateTimeFormatter.ofPattern("mm:ss"));

     return new Athlete(
             athleteNumber,
             athleteAttributes[1],
             athleteAttributes[2],
             skiTimeResults,
             athleteAttributes[4],
             athleteAttributes[5],
             athleteAttributes[6]
     );

}

请帮我克服这个问题

好吧,LocalDateTime 需要一个日期组件和一个有效的时间组件。您的 30:27 文本不包含任何内容:显然,30:27 作为 挂钟时间 不存在。

您似乎在寻找 持续时间。使用 Duration。请注意 Duration 没有成功 parse 文本 30:27 的方法,因此我们必须将其转换为 ISO period/duration 字符串:

String[] components = athleteAttributes[3].trim().split(":");
String durationStr = String.format("PT%sM%sS", components[0], components[1]);
Duration duration = Duration.parse(durationStr);

或者,您可以使用

String[] components = athleteAttributes[3].trim().split(":");
int minutes = Integer.parseInt(components[0]);
int seconds = Integer.parseInt(components[1]);
Duration duration = Duration.ofMinutes(minutes).plusSeconds(seconds);

你写的没有意义

只是阅读并思考:分+秒值与'local date time'的概念绝对相关。就像写:

Apple a = new Caravan();

同样疯狂。

那些分钟+秒代表一个持续时间

不幸的是,DateTimeFormatter 基本上是为解析挂钟日期和时间而设计的。

这里有一个更核心的问题...

挂钟时间和持续时间的问题

挂钟时间和持续时间完全无关,但人类并不像这样:

比赛的电视和印刷结果往往表明某人,例如。 运行“04:23”一英里,与“午夜 23 秒 4 分”的挂钟时间一模一样。但是,这两个概念之间绝对没有任何关系。这意味着当计算机需要处理这些东西时会非常混乱:Is "04:23":

  • 有人 运行 跑了 4 小时 23 分和未指定的秒数。
  • 有人 运行 跑了 4 分 23 秒。
  • 凌晨4点23分
  • 现在是午夜 23 秒 4 分。

个个都有道理;这取决于上下文。

一般来说,当人类有奇怪的、不一致的行为时,软件应该凑合一下,但在 ISO(标准)世界中,这种混淆是如此令人讨厌,以至于他们断然拒绝处理像“04:23”这样的东西作为将 'a duration of 4 minutes and 23 seconds'.

的概念放入文本的公平方式

相反,您会得到 ISO8601 Durations format,它将写为 "PT30m27s"(P 表示:这是一段时间,然后 T 表示我们不会指定任何周或几天,我们直接进入次日的内容,然后是 30 分 27 秒。您可以开箱即用 Duration.parse("PT30m27s") 解析它,但您没有那种字符串输入.

就 date/time API 而言,您所拥有的是挂钟时间,只不过是挂钟时间。

我解释这一切是为了让你明白为什么这个方法根本不存在:没有:

Duration d = Duration.parse("30:27", DateTimeFormatter.ofPattern("mm:ss"));

也没有任何其他方法可以直接将字符串+日期时间格式模式转换为 Duration 的实例。

但是等等!有窍门...

我们将字符串视为挂钟时间,然后获取午夜与该时间之间的持续时间。

DateTimeFormatter formatter = DateTimeFormatter.of("[HH:]mm:ss");
LocalTime lt = LocalTime.parse("30:27", formatter);
Duration d = Duration.between(LocalTime.MIN, lt);

注意:已编辑:添加了此处必需的 [HH:]

这实现了您的目标:仅使用 java.time.

中的工具,在指定格式字符串时具有可读性和灵活性