【问题标题】:Format and convert integer number to minutes and seconds格式化整数并将其转换为分钟和秒
【发布时间】:2020-03-17 21:19:04
【问题描述】:

在我的 Java 应用程序中,我们有一个文本字段,用户可以在其中输入数字,我们需要正确解析该数字以将其格式化为分钟和秒。以下是可能值和需要生成的值的表格:

2     -> 02:00 OR 00:02
21    -> 00:21
215   -> 02:15
2157  -> 21:57

2:7   -> 02:07 OR 03:10
2:1   -> 02:01
2:71  -> 03:11
2:07  -> 02:07
20:7  -> 20:07 OR 21:10
20:61 -> 21:01

OR 部分我仍在考虑最好的方法。

我确定这个问题之前已经解决了,我只是在寻找一个已经存在的可以处理这个问题的库。

【问题讨论】:

  • 您的 2:7 示例(转换为 2:70)是否仅适用于数字 7,或者此转换也适用于 2:8 和 2:9?
  • 是的,它肯定可以应用于任何数字,我只是举例说明
  • 21可以变成21:00吗?为什么不?我花了一点时间才理解 2:7 如何变成 3:10:您正在考虑是否可以理解尾随 0,所以 2:7 -> 2:70 -> 2 小时 70 分钟 = 3 小时 10 分钟 -> 3:10。我的感觉是解释为 02:07,但你应该知道得更好。

标签: java parsing time


【解决方案1】:

根据您使用的选项,您可以使用标准 java.time 功能来实现

LocalTime time = LocalTime.of(value / 100, value % 100);
String timeString = time.format(DateTimeFormatter.ofPattern("HH:mm"));

例子

for (int value : values) {
    LocalTime time = LocalTime.of(value / 100, value % 100);
    String timeString = time.format(DateTimeFormatter.ofPattern("HH:mm"));
    System.out.println(timeString);
}

00:02
00:21
02:15
21:57

【讨论】:

  • 有点不错。但是如果输入是持续时间,次数,正如我怀疑的那样,LocalTime 是使用错误的类。我们有一个 Duration 类。
【解决方案2】:

考虑禁止输入超过 59 秒。我怀疑用户是否有任何理由想要这样做,所以 2:71 更有可能是一个错字,当你让他们意识到这一点时,你可以帮用户一个忙。至少只在没有分钟的情况下允许它。

正则表达式和持续时间

无论如何,对于所提出的问题,一个建议是使用正则表达式和 Duration 类,如下所示:

    Pattern durationPattern = Pattern.compile("(?:(\\d{1,2}?):?)??(\\d{1,2})");

    String[] inputs = { "2", "21", "215", "2157", "2:7",
            "2:1", "2:71", "2:07", "20:7", "20:61" };

    for (String input : inputs) {
        Matcher m = durationPattern.matcher(input);
        if (m.matches()) {
            String minuteStringOrNull = m.group(1);
            String secondString = m.group(2);
            Duration dur = minuteStringOrNull == null ? Duration.ZERO : Duration.ofMinutes(Integer.parseInt(minuteStringOrNull));
            dur = dur.plusSeconds(Integer.parseInt(secondString));

            String durationString = String.format("%02d:%02d", dur.toMinutes(), dur.toSecondsPart());

            System.out.format("%-5s -> %s%n", input, durationString);
        } else {
            System.out.println("Invalid input: " + input);
        }
    }

这段代码的输出是:

2     -> 00:02
21    -> 00:21
215   -> 02:15
2157  -> 21:57
2:7   -> 02:07
2:1   -> 02:01
2:71  -> 03:11
2:07  -> 02:07
20:7  -> 20:07
20:61 -> 21:01

我自己不喜欢的是正则表达式很难阅读。 (?:(\\d{1,2}?):?) 是一个非捕获组,(?:) 在数学和编程中与括号相同。而??在它说它可能存在也可能不存在并且不情愿地接受它之后,即先尝试没有它,然后尝试它。这样,当数字很少时,我们将它们用于秒而不是分钟。在(\\d{1,2}?) 组内部是一个捕获组,由 1 或 2 位数字(表示分钟)组成,同样不情愿,更喜欢 1 而不是 2。:? 表示 1 或两位数字后面可能有也可能没有冒号。最后,(\\d{1,2}) 是另一个 1 位或 2 位数字(秒)的捕获组。捕获组是我们在后面的代码中使用m.group() 取出的(它们从 1 开始编号)。

如果您最终决定采用其他解释,您可能可以相应地修改想法和/或代码。

更具可读性的替代方案

您可能更喜欢更易于阅读的代码,即使它更长。在这种情况下,手动解析可能比使用正则表达式更好。我相信您可以按照以下不完整的方式构建算法(未经测试)。

    String[] parts = input.split(":", 3);
    if (parts.length == 1) { // no colon
        if (input.length > 2) {
            // take last two digits as seconds, everything else as minutes
        } else {
            // take everything as seconds
        }
    } else if (parts.length == 2) {
        // take minutes from parts[0] and seconds from parts[1]
    } else {
        // invalid input, too many colons
    }

仍然像以前一样使用Duration 类。

现有的库?

这对于 Stack Overflow 来说是题外话,但现在我们开始了:我不太清楚,但您可能会看到 Time4JJoda-Time 是否可以帮助您。

链接

Documentation of regular expressions in Java

【讨论】:

  • 感谢您的回答。我已经编辑并添加了一个更长但可能更容易阅读的替代方案。
猜你喜欢
  • 1970-01-01
  • 2020-09-04
  • 1970-01-01
  • 1970-01-01
  • 2012-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多