【问题标题】:Is there a equivalent to ChronoUnit.between that returns fraction instead of integer?是否有等效于 ChronoUnit.between 的返回分数而不是整数?
【发布时间】:2016-06-13 09:09:32
【问题描述】:

ChronoUnit.HOURS.between(start, end) 等方法返回 long,所以我无法从那里得到分数。

是否有可以返回分数的替代方法/方法?

【问题讨论】:

    标签: java java-8 java-time jsr310


    【解决方案1】:

    ChronoUnit.HOURS.between(start, end) 的全部意义在于获取两个时间点之间的 HOURS 数。例如:两者之间要么是 1 小时,要么是 2 小时,没有 1.5658 小时*这样的东西。如果您需要更高的精度,请使用另一个 ChronoUnit,即分钟或秒。

    小数的问题在于,它们通常基于 10,而时间单位是基于圆的分数(360°、2pi 等),最好用整数的分数表示,如 1/4、1/ 8、1/2 等,而不是浮点值。这里的关键字是“浮点数”,您可以通过移动点或将基值乘以 10 的幂并使用单位前缀来表示值(即 1.5 * 10^3 == 1500000 * 10^-3 ,其中 10^3 是公斤,10^-3 是毫),但你不能用天、小时、分钟和秒来做到这一点。没有千小时或毫天之类的东西,您不能通过乘以 10* 的幂来简单地将小时转换为分钟。

    在现实生活中,没有人会说“现在是 1 小时 8.3%”或“6.5 小时后”——因为这通常会导致混乱(6.30 对 6:30)——所以说“现在是 1 小时 5 分钟”更实际”或“5过去x”或“四分之一到x”。

    因此,在时间 API* 中计算小数并没有真正的实际用途。但如果你需要它(即用于计算目的),你可以很简单地计算它。

    如果您需要分数 - 即分钟或秒 - 您必须使用相应的 ChronoUnit,即 ChronoUnit.MINUTESChronoUnit.SECONDS,并将其除以您想要的整体所需的时间单位量有一小部分。例如

    • 60 分钟变成一小时
    • 3600 秒等于一小时
    • 3600000 毫秒赚一个小时,等等。
    • 60 秒等于一分钟
    • ...

    您可以使用简单的数学即以分钟精度计算分数,即

    double fracH = (double)ChronoUnit.MINUTES.between(start,end) / 60;
    

    您也可以使用Duration,它也提供了between 方法。持续时间可以轻松转换为分钟、小时等。

    Duration dur = Duration.between(start, end);
    double fracH = (double)dur.toMinutes() / 60;
    

    要获得最高精度,您必须计算最小时间单位的分数,即纳秒或毫秒

    double fracHns = (double)dur.toNanos() / 3_600_000_000_000;
    

    您甚至可以使用Duration 来获取基本(100%)值:

    //fraction of an hour
    double fracHns = (double)dur.toNanos() / Duration.ofHours(1).toNanos();
    
    //fraction of a minute
    double fracMns = (double)dur.toNanos() / Duration.ofMinutes(1).toNanos();
    

    或更笼统地说,如David SN posted

    TemporalUnit unit = ChronoUnit.HOURS;
    double frac = (double)Duration.between(start, end).toNanos() 
                  / Duration.of(1, unit).toNanos();
    

    *) 没有例外:为了让事情变得困难,对于小于 1 秒的单位,计算基数会发生变化,因为它会以 10 为基础,即毫秒(1/1000),微秒(1 /1000000th),... 所以对于秒和更小,通常使用小数,例如:1.74 秒,因为通过简单地移动小数分隔符将其转换为下一个更小的时间单位很简单:

    1.74 s <-> 1740.0 ms. 
    

    但这几个小时没那么容易:

    1.74 hours <-> 104.40 minutes.
    

    【讨论】:

      【解决方案2】:

      ChronoUnit 中没有获取给定时间单位时差十进制值的方法。

      您可以创建一个实用程序方法来实现此功能。 Duration 类可用于此目的。这可以得到最小单位的差异并将其转换回(带小数)到所需的单位:

      public static double between(Temporal startInclusive, Temporal endExclusive, ChronoUnit unit) {
          Duration duration = Duration.between(startInclusive, endExclusive);
          long conversion = Duration.of(1, unit).toNanos();
          return (double) duration.toNanos() / conversion;
      }
      

      【讨论】:

      • 在 MONTHS 和 YEARS 内将无法工作(它会崩溃),因为它们没有修复持续时间
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-11-15
      • 2018-11-16
      • 1970-01-01
      • 2021-10-17
      • 2017-09-21
      • 2018-05-16
      • 1970-01-01
      相关资源
      最近更新 更多