Methods such is ChronoUnit.HOURS.between(start, end)
returns long
so I can't get the fraction from there.
Is there an alternative method/approach that would return a fraction?
The whole point of ChronoUnit.HOURS.between(start, end)
is to get the number of HOURS between the two timepoints. For example: it's either 1 or 2 hours between, there is no such thing as 1.5658 hours*. If you need more precicion, use another ChronoUnit, i.e. Minutes or seconds.
The problem with decimal fractions is, that they are usually based on 10, while time units are fractions based on a circle (360°, 2pi, etc) which are better expressed in fractions of integers like 1/4, 1/8, 1/2, etc. and not in a floating point value. The keyword here is "floating point", you could express a value by moving the point or multiply a base-value with powers of 10 and use a prefix to the unit (i.e. 1.5 * 10^3 == 1500000 * 10^-3, where 10^3 is kilo and 10^-3 is milli), but you can't do that with days, hours, minutes and seconds. There is no such thing as kilo-hour or milli-days and you can't simply translate hours to minutes by multipling a power of 10*.
In real life nobody would say "it's 1 hour and 8.3%" or "6.5 hours later" - as this usually ends up in confusion (6.30 vs 6:30) - so it's more practical to say "it's 1hr and 5mins" or "5 past x" or "a quarter to x".
So there is no real practical use for having a decimal fraction calculation in a time API*. But in case you need it (i.e. for computational purposes), you may quite simply calculate it.
If you require a fraction - i.e. minutes or seconds - you have to use the corresponding ChronoUnit
, i.e. ChronoUnit.MINUTES
or ChronoUnit.SECONDS
, and devide it by the amount of time units required for the whole you'd like to have a fraction of. For example
You may calculate the fraction with minute-precision using simple math i.e.
double fracH = (double)ChronoUnit.MINUTES.between(start,end) / 60;
As alternative you could use Duration
which offers a between
method, too. A duration can be easily converted into Minutes, Hours etc.
Duration dur = Duration.between(start, end);
double fracH = (double)dur.toMinutes() / 60;
To get the highest precision, you have to calculate the fraction on the smallest timeunit, i.e. nanos or millis
double fracHns = (double)dur.toNanos() / 3_600_000_000_000;
You may even use Duration
to get the base (the 100%) value:
//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();
Or more general, as David SN posted
TemporalUnit unit = ChronoUnit.HOURS;
double frac = (double)Duration.between(start, end).toNanos()
/ Duration.of(1, unit).toNanos();
*) No rule without exception: To make things difficult, for time units the calculation base changes for units smaller than 1 second, because then it gets 10-based, i.e. milli-seconds (1/1000th), microseconds (1/1000000th),... So for seconds and smaller it is common to use decimal fractions, for example: 1.74 second, because it is simple to translate it to the next-smaller time unit by simply moving the decimal separator:
1.74 s <-> 1740.0 ms.
But it's not that easy for hours:
1.74 hours <-> 104.40 minutes.
There is no methods in ChronoUnit
to get the decimal value of the time difference in a given time unit.
You could create a utility method to implement this functionality. The class Duration
could be used for this purpose. This could be done getting the difference in the smallest unit and converting it back (with decimals) to the required unit:
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With