そのようなメソッドはChronoUnit.HOURS.between(start, end)
リターンなlong
ので、そこから分数を取得できません。
分数を返す代替方法/アプローチはありますか?
全体のポイントはChronoUnit.HOURS.between(start, end)
、2 つのタイムポイント間の 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 分です」または「 x から 5 度」または「x までの 4 分の 1」。
そのため、時間 API* で小数の計算を行うことは実際には実用的ではありません。しかし、それが必要な場合 (計算目的など) は、非常に簡単に計算できます。
分数または秒数が必要な場合は、対応するChronoUnit
、つまりChronoUnit.MINUTES
またはを使用ChronoUnit.SECONDS
して、分数を取得する全体に必要な時間単位で割る必要があります。例えば
簡単な数学を使用して、分精度で分数を計算できます。
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が投稿したように
TemporalUnit unit = ChronoUnit.HOURS;
double frac = (double)Duration.between(start, end).toNanos()
/ Duration.of(1, unit).toNanos();
*) 例外のないルール: 難しいことに、時間単位の場合、1 秒未満の単位の計算ベースが変わります。これは、10 ベース、つまりミリ秒 (1/1000)、マイクロ秒 (1/1000000) になるためです。 ,... したがって、秒以下の場合は小数を使用するのが一般的です。たとえば、1.74 秒です。これは、小数点区切り記号を移動するだけで、次に小さい時間単位に簡単に変換できるためです。
1.74 s <-> 1740.0 ms.
しかし、それは何時間も簡単ではありません。
1.74 hours <-> 104.40 minutes.
ChronoUnit
特定の時間単位で時差の 10 進値を取得するメソッドはありません。
この機能を実装するユーティリティ メソッドを作成できます。クラスDuration
はこの目的に使用できます。これは、最小単位の差を取得し、それを (10 進数で) 必要な単位に変換することで実行できます。
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;
}