0

我正在制作一个旨在通过军事时间获取经过时间的程序,这就是我到目前为止所得到的:

public class TimeInterval {
    private int firstTime;
    private int secondTime;

    public TimeInterval(int _first,int _second) {
        if (_first < 0 || _second < 0) {
            System.out.println("ERROR INVALID INPUT");
            System.exit(0);
        }
        else if (_first > 2400 || _second > 2400) {
            System.out.println("ERROR INVALID INPUT");
            System.exit(0); 
        }
        else
            firstTime = Math.max(_first, _second);
            secondTime = Math.min(_first,_second);
        }
    }

    public int getHours() {
        return (Integer.parseInt(Integer.toString(firstTime).substring(0, 2)))-(Integer.parseInt(Integer.toString(secondTime).substring(0, 2)));
    }
}

除了处理 _first 或 _second 从 0000 到 0700 的输入外,该程序大部分工作。想法是它们被读取为军事时间,但 java 将它们读取为基数 8 整数,因此当 _first = 0700 和 _second 时= 1400 我得到 448 或其他东西。无论如何我可以确保当 _first 和 _second 输入到 Math.min 时,它们被读取为基数 10 而不是基数 8。

4

1 回答 1

1

您似乎假设军事时间始终是 4 位数字,并带有适当数量的前导零,从 0000 到 2359。您不能在 int 中表示军事时间的概念,因为 int 不一定有 4 位数字。相同的数字可以格式化为 6、06、006、0006 或 000000006。在内部它只是相同的 32 位。所以什么时候firstTime是 700(或 0700),然后Integer.toString(firstTime).substring(0, 2))取 700 的前两位数并得出 70(不是 7)。所以new TimeInterval(700, 1400).getHours()产生 -56(不是 7)。如果firstTime是 9 (0009) 或更少,您的代码可能会因StringIndexOutOfBoundsException.

一种解决方案是将您的军事时间传递给String始终长度为 4 的 a。然后您的子字符串操作将始终采用前 2 位数字,即小时数。如果您坚持使用int,另一种解决方案是模 100 运算来获得小时数:firstTime % 100.

您提到了以 8 为基数,也称为八进制数。您显示的代码中没有任何内容会导致使用基数 8。当然,如果你使用你的类 like new TimeInterval(0700, 1400),那么 Java 将把 0700 作为基数 8,所以 448,你是对的。在这种情况下,您获得的小时数将为 14 - 44 = -30。再次传递一个字符串将解决它。

深入挖掘并找到一个好的解决方案

我还想建议:

  • 当时间是 1059 和 1202 时,它们之间有 1 小时 3 分钟。在这种情况下,您不希望小时数为 1 而不是 2 吗?
  • 使用LocalTimejava.time 类(现代 Java 日期和时间 API)作为您一天中的时间。当您在某个界面中使用军用时间时,请将其保留在界面中,无论是在String还是int形式或两者兼而有之。TimeInterval在构建实例时进行适当的转换。

所以你的班级可能会变成:

public class TimeInterval{
    private static final DateTimeFormatter FORMATTER_FOR_MILITARY_HOURS
            = DateTimeFormatter.ofPattern("HHmm");
    
    private LocalTime firstTime;
    private LocalTime secondTime;

    /** Main constructor */
    public TimeInterval(LocalTime firstTime, LocalTime secondTime){
        if (firstTime.isAfter(secondTime)) {
            // Switch around
            this.firstTime = secondTime;
            this.secondTime = firstTime;
        } else {
            this.firstTime = firstTime;
            this.secondTime = secondTime;
        }
    }

    /** Convenience constructor accepting military hours */
    public TimeInterval(String first, String last) {
        this(LocalTime.parse(first, FORMATTER_FOR_MILITARY_HOURS),
                LocalTime.parse(last, FORMATTER_FOR_MILITARY_HOURS));
    }

    public int getHours(){
        long differenceInHours = ChronoUnit.HOURS.between(firstTime, secondTime);
        return Math.toIntExact(differenceInHours);
    }

}

这也为我们提供了免费的范围检查:LocalTime仅处理从 00:00 到 23:59:59.999999999 的时间。所以超出这个范围的时间会抛出异常(对不起,2400无法处理)。如果字符串的格式不正确,也会发生同样的情况,例如长度不是 4 或分钟数大于 59。

便利构造函数中的this(...<code>) 是对另一个构造函数的调用,该构造函数接受LocalTIme作为参数。

ChronoUnit.between()返回一个长。由于我们知道最多可以有 23 小时,因此我们可以安全地转换为int. Math.toIntExact()为我们这样做。

于 2020-10-03T06:17:59.993 回答