SimpleDateFormat 并且不允许超过 12 小时

SimpleDateFormat and not allowing it to go above 12 hours

所以我想扩展这个方法,让用户输入有效的 12 小时时间。而且我有它可以正常工作。但我想要这样,如果小时超过 12 小时或分钟超过 59,那么它会提示再次执行。但现在它只会通过添加时间来转换时间。 还有更有效的方法来写这个吗? (就像没有 Date newTime = sdf.parse(startTime); 并且拥有它以便用户可以只输入一个字符串并让它检查它的格式是否正确?

public static void userInput(){
    Scanner in = new Scanner(System.in);
    SimpleDateFormat sdf = new SimpleDateFormat("hh:mm aa");
    String startTime;

    System.out.print("What is the start time?: ");
    boolean success = false;
    while (success != true){
        try{
        startTime = in.nextLine();
        Date newTime = sdf.parse(startTime);
        startTime = sdf.format(newTime);


        System.out.println(startTime);

        success = true;
        }
        catch(Exception e){
            System.out.println("Not a valid time. Please use this format (HH:MM AM)");
        }
    }
}

您正在经历 SimpleDateFormat 的设计行为。这种行为对大多数人来说都是一种负面的惊喜。

有两种解决方案:推荐的一种和不推荐的一种。

推荐方案:LocalTime

        DateTimeFormatter timeFormat = DateTimeFormatter.ofPattern("hh:mm a", Locale.ROOT);
        try {
            LocalTime lt = LocalTime.parse(startTime, timeFormat);
            startTime = lt.format(timeFormat);
            System.out.println(startTime);
        } catch (DateTimeParseException e) {
            System.out.println("Not a valid time. Please use this format (HH:MM AM)");
        }

LocalTime 和一些其他设计更好、对程序员更友好的 classes 在 Java8 中被引入。如果你不能使用 Java8,那里又是两种解决方案: (1) 求助于气馁的解决方案,见下文。 (2) 使用 Java 8 日期和时间 classes 到 Java 6 和 7: ThreeTen Backport 的 backport(我没有使用 ThreeTen Backport 的经验)。

在代码中,请指定正确的语言环境,而不是 Locale.ROOT。我不知道 AM 和 PM 在某些语言环境中是否有其他名称,所以我想确保我们使用的语言环境与用户在这一点上的输入一致。

不鼓励的解决方案:setLenient()

    SimpleDateFormat sdf = new SimpleDateFormat("hh:mm aa");
    sdf.setLenient(false);

SimpleDateFormat 默认为 lenient 并接受 09:63 作为 10:03 和 14:00 AM 作为 02:00 下午。当您 setLenient(false) 时,它将不再以这种方式接受超出范围的值,但会像您预期的那样抛出 ParseException

只是检查格式是否正确

在任一解决方案中,检查格式的最佳方法是您已经在做的事情:您尝试解析它并捕获相关的异常类型。只是不要只捕获 Exception,要具体一些,因为异常可能来自许多其他原因。也就是说,使用推荐的解决方案捕获 DateTimeParseException,使用不推荐的解决方案捕获 ParseException

此外,如果你想存储时间以供以后使用,将它存储为LocalTime(或者class最能反映你的需求)可能更方便和面向对象而不是 String.