如何将一个持续时间除以另一个?

How to divide one Duration by another?

给定两个 java.time.Duration 个实例,如何计算一个 Duration 适合另一个的总次数?

使用 first.toNanos() / second.toNanos() 似乎很明显,但此方法的 Javadoc 引入了一个小问题:

If this duration is too large to fit in a long nanoseconds, then an exception is thrown.

我们如何在没有溢出风险的情况下计算这个除法?

更新:我正在实施 Token Bucket Algorithm。为此,我需要知道自上次检查以来已经过去了多少 "periods",以便用额外的令牌填充存储桶。 我不能简单地放弃纳秒精度,因为速率可能以纳秒为单位指定。

我想通了:

/**
 * @param first  the first duration
 * @param second the second duration
 * @return {@code first / second}
 * @throws IllegalArgument of {@code first}, {@code second} are negative or if {@code second} is zero
 */
public static long divide(Duration first, Duration second)
{
    if (first.isNegative())
      throw new IllegalArgumentException("first may not be negative");
    if (second.isNegative())
      throw new IllegalArgumentException("second may not be negative");
    if (second.isZero())
      throw new IllegalArgumentException("second may not be zero");
    BigDecimal firstDecimal = toSeconds(first);
    BigDecimal secondDecimal = toSeconds(second);
    return firstDecimal.divideToIntegralValue(secondDecimal).longValueExact();
}

/**
 * @param duration a duration
 * @return the number of seconds in the duration
 */
public static BigDecimal toSeconds(Duration duration)
{
    return BigDecimal.valueOf(duration.getSeconds()).add(BigDecimal.valueOf(duration.getNano(), 9));
}

当您查看 javadoc 时,您会发现 Duration class 实际上使用秒和纳秒来表达自己。正如那里所写:

The duration uses nanosecond resolution with a maximum value of the seconds that can be held in a long. This is greater than the current estimated age of the universe.

所以您应该只使用秒值。或者,如果您确实需要精确值(也包括纳秒),则使用 BigInteger。您甚至可以在这种计算中包括纳秒。

对于 Java 9 及更高版本,只有 the method for this on the Duration type