英文:
Formatting hour in java 20h 10m 5000s to 20h 10m 10s
问题
我正在尝试创建一个小程序,我们提供一个错误的时间,例如:20小时 10分钟 5000秒,然后将其转换为返回给我 20小时 10分钟 50秒。但是很抱歉,我无法展示给您代码,以便查看是否能够帮助我,非常感谢:)
import java.util.Date;
import java.text.SimpleDateFormat;
import javax.swing.JOptionPane;
public class EejercicioBasico3 {
public static void main(String[] args) {
Date date = new Date();
SimpleDateFormat dateForm = new SimpleDateFormat("HH:mm:ss");
String UserDate = dateForm.format(JOptionPane.showInputDialog("Escriba una hora en formato hh-mm-ss"));
System.out.println(date);
System.out.println(UserDate);
}
}
<details>
<summary>英文:</summary>
I am trying to create a small program that we give a wrong time for example: 20h 10m 5000s and that transforms it giving me back 20h 10m 50s. But I am unable to show you the code to see if you can help me, thank you very much :)
import java.util.Date;
import java.text.SimpleDateFormat;
import javax.swing.JOptionPane;
public class EejercicioBasico3 {
public static void main(String[] args) {
Date date = new Date();
SimpleDateFormat dateForm = new SimpleDateFormat("HH:mm:ss");
String UserDate = dateForm.format(JOptionPane.showInputDialog("Escriba una hora en formato hh-mm-ss"));
System.out.println(date);
System.out.println(UserDate);
}
}
</details>
# 答案1
**得分**: 2
## 移除多余的数字
我从你的问题和评论中理解到,你假设用户可能会因失误而输入过多的数字。我进一步假设每个数字可能在从0或00到59的区间内,任何使数字大于59或超过两位数的数字都应该被移除。这可能不是完美的解决方案,但可以让你开始。
```java
String inputTimeString = "20h 10m 5000s";
String outputTimeString = inputTimeString.replaceAll("([6-9]|[0-5]\\d)\\d+", "$1");
System.out.println(outputTimeString);
输出结果为:
> 20h 10m 50s
正则表达式首先匹配在范围6-9内的数字,或者以0到5开头的两位数字,以确保我们最多只有59。这个数字或这些数字被捕获为一个组,正则表达式中使用圆括号将组括起来。在组后,匹配任意数量的多余数字。在替换字符串中,我使用$1
来表示这些数字应该被替换为捕获组1中匹配的内容(在这种情况下是唯一的捕获组)。
再试一个例子:
String inputTimeString = "60h 010m 777s";
输出结果为:
> 6h 01m 7s
备注: 如果这是学校的基础练习,你的老师可能会有另一种解决方案,但你可以更好地判断。如果你还没有学习正则表达式,那么最好不要提交使用正则表达式的解决方案。也许你应该遍历输入字符串,并将那些合适的字符添加到一个字符串缓冲区中,用于收集输出。
将多余的秒转换为分钟和小时
如果你想要将超过59秒的多余秒数转换为分钟和小时,可以使用Duration
类:
String isoTimeString = "PT" + inputTimeString.replaceAll(" ", "");
Duration dur = Duration.parse(isoTimeString);
String outputTimeString = String.format("%dh %dm %ds",
dur.toHours(), dur.toMinutesPart(), dur.toSecondsPart());
System.out.println(outputTimeString);
输出结果为:
> 21h 33m 20s
Duration.parse()
需要 ISO 8601 格式。这可以通过在你的格式前加上 PT
(表示时间段)并去除空格来获得。String.format()
调用重新生成了你的格式。
始终避免使用 Date 和 SimpleDateFormat
你尝试使用的 SimpleDateFormat
和 Date
类设计不佳,已经过时,并且从未适用于这样的任务。我建议你永远不要使用它们,而应始终使用现代的 Java 日期和时间 API - java.time
来处理时间。Duration
类是 java.time
的一部分。
链接
- Oracle 教程:日期时间 解释了如何使用
java.time
。 - Wikipedia 文章:ISO 8601
英文:
Removing excess digits
I tend to understand from your question and comments that you are assuming that the user may type too many digits by mistake. I am further assuming that each number may be in the interval from 0 or 00 to 59, and any digits that make the number greater than 59 or wider than two digits are to be removed. It’s probably not perfect, but may get you started.
String inputTimeString = "20h 10m 5000s";
String outputTimeString
= inputTimeString.replaceAll("([6-9]|[0-5]\\d)\\d+", "$1");
System.out.println(outputTimeString);
Output is:
> 20h 10m 50s
The regular expression first matches either a digit in the range 6 – 9 or two digits starting with 0 through 5 to ensure that we got at most 59. This or these digits are captured as a group using round brackets around the group in the regexp. After the group any number of excess digits is matched. In the replacement string I use $1
to denote that the digits should be replaced with just what was matched in capturing group no. 1 (the only capturing group in this case).
Try another example:
String inputTimeString = "60h 010m 777s";
> 6h 01m 7s
Reservation: If this is a basic exercise from school, your teacher may have another solution in mind, but you can judge that better. If you haven’t learnt regular expressions, you probably should not hand in a solution that uses them. Maybe you were expected to iterate through the input string and add characters that are OK to a string buffer where you collect your output.
Converting excess seconds to minutes and hours
If instead you want excess seconds — over 59 seconds — converted to minutes and hours, use the Duration
class:
String isoTimeString = "PT" + inputTimeString.replaceAll(" ", "");
Duration dur = Duration.parse(isoTimeString);
String outputTimeString = String.format("%dh %dm %ds",
dur.toHours(), dur.toMinutesPart(), dur.toSecondsPart());
System.out.println(outputTimeString);
> 21h 33m 20s
Duration.parse()
requires ISO 8601 format. This is obtained from your format by prefixing PT
(think period of time) and removing the spaces. The String.format()
call reproduces your format.
Always avoid Date and SimpleDateFormat
The classes you were trying to use, SimpleDateFormat
and Date
, are poorly designed and long outdated and were never meant for a job like this. I recommmend that you never use them and always use java.time, the modern Java date and time API, for your time work. The Duration
class is part of java.time.
Links
- Oracle tutorial: Date Time explaining how to use java.time.
- Wikipedia article: ISO 8601
答案2
得分: 1
依我看,底线就是...不要接受这样的输入:20h 10m 5000s
。虽然数据是通过一个输入对话框窗口提供的,但仍然可以验证其是否包含所需的格式(在对话框中明确显示为示例),如果不是,则通知用户重新输入。您的代码实际上不应该适应每个打字错误并自动更正。但它应该确定存在打字错误,并通知用户进行更正或完全放弃输入的数据。您的应用程序制定了规则,而不是用户(不过不幸的是,这可能并非对所有情况都适用)。这可能听起来很直接,但是你不能使每件事都白痴化,因为明天,肯定会有一个更好的白痴。让那个白痴做对。
确定您的应用程序的时间输入规则:
- 时间应由三个特定单位组成:小时、分钟和秒。
- 时间采用24小时制,这意味着没有上午或下午之分。
- 每个时间单位(小时、分钟或秒)应由两个整数数字组成(例如:15-32-05)。
- 应该应用分隔符字符来分隔每个时间单位。在这种情况下,允许使用连字符(-)或减号字符。
String userTime = "";
while (userTime.isEmpty()) {
userTime = JOptionPane.showInputDialog(null, "<html>Enter a time in "
+ "<font color=red><b>hh-mm-ss</b></font> format:<br><br></html>");
if (userTime == null) {
JOptionPane.showMessageDialog(null, "Time entry Canceled!", "Entry Canceled",
JOptionPane.WARNING_MESSAGE);
return;
}
if (!userTime.matches(
"^([0-1][0-9][-]|[2][0-3][-])([0-5][0-9][-])([0-5][0-9])$")) {
JOptionPane.showMessageDialog(null, "Invalid Time format supplied!",
"Invalid Entry", JOptionPane.WARNING_MESSAGE);
userTime = "";
}
}
String[] timeUnits = userTime.split("-");
String time = new StringBuilder("").append(timeUnits[0]).append("h ")
.append(timeUnits[1]).append("m ").append(timeUnits[2])
.append("s").toString();
JOptionPane.showMessageDialog(null, "<html>User supplied the time of:<br><br>"
+ "<center><font color=blue><b>" + time + "</b></font></center></html>",
"Invalid Entry", JOptionPane.INFORMATION_MESSAGE);
显然您不需要在循环中执行此类操作,但我相信您已经理解了。
英文:
In my opinion the bottom line would be...just don't accept an entry of: 20h 10m 5000s
. Although the data is supplied through an Input Dialog window it can still be validated to contain the desired format (which is clearly shown as an example within the dialog) and if it isn't, inform the User to enter it again. Your code really shouldn't need to accommodate every typo and automatically correct it. It should however determine that there is a typo and inform the User to correct it or discard the input data altogether. Your application sets the rules, not the User (unfortunately however this may not be the case for everything). This may seem blunt but, you can't make everything idiot proof because tomorrow, there will just be a better idiot. Make the idiot do it right.
Determine your application's Time Entry rules:
- Time is to be in three specific units: Hours, Minutes, and
Seconds. - Time is in 24 hour format meaning there is no such thing as AM or PM.
- Each time unit (Hour, Minute, or Second) is to be comprised of two integer digits (ex: 15-32-05).
- A separator character must be applied to separate each time
unit. The allowable character in this case is the Hyphen (-) or Minus character.
String userTime = "";
while (userTime.isEmpty()) {
userTime = JOptionPane.showInputDialog(null, "<html>Enter a time in "
+ "<font color=red><b>hh-mm-ss</b></font> format:<br><br></html>");
if (userTime == null) {
JOptionPane.showMessageDialog(null, "Time entry Canceled!", "Entry Canceled",
JOptionPane.WARNING_MESSAGE);
return;
}
if (!userTime.matches(
"^([0-1][0-9][-]|[2][0-3][-])([0-5][0-9][-])([0-5][0-9])$")) {
JOptionPane.showMessageDialog(null, "Invalid Time format supplied!",
"Invalid Entry", JOptionPane.WARNING_MESSAGE);
userTime = "";
}
}
String[] timeUnits = userTime.split("-");
String time = new StringBuilder("").append(timeUnits[0]).append("h ")
.append(timeUnits[1]).append("m ").append(timeUnits[2])
.append("s").toString();
JOptionPane.showMessageDialog(null, "<html>User supplied the time of:<br><br>"
+ "<center><font color=blue><b>" + time + "</b></font></center></html>",
"Invalid Entry", JOptionPane.INFORMATION_MESSAGE);
Obviously you don't need to do this sort of thing in a loop but you get the idea I'm sure.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论