考虑禁止输入超过 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 来说是题外话,但现在我们开始了:我不太清楚,但您可能会看到 Time4J 或 Joda-Time 是否可以帮助您。
链接
Documentation of regular expressions in Java