Reputation: 1098
I need some explination why this code does not compile:
Duration duration = Duration.from(ChronoUnit.DAYS);
Error :
The method from(TemporalAmount) in the type Duration is not applicable for the arguments (ChronoUnit)
As the the documentation here says :
public static Duration from(TemporalAmount amount) Obtains an instance of Duration from a temporal amount. This obtains a duration based on the specified amount. A TemporalAmount represents an amount of time, which may be date-based or time-based, which this factory extracts to a duration.
The conversion loops around the set of units from the amount and uses the duration of the unit to calculate the total Duration. Only a subset of units are accepted by this method. The unit must either have an exact duration or be ChronoUnit.DAYS which is treated as 24 hours. If any other units are found then an exception is thrown.
Parameters: amount - the temporal amount to convert, not null Returns: the equivalent duration, not null Throws: DateTimeException - if unable to convert to a Duration ArithmeticException - if numeric overflow occurs
I know that there are other ways of creating duration instance but I need some explination why this one does not work.
EDIT
When I change like this (Because Period implements TemporalAmount Interface) :
Duration d1 = Duration.from(Period.ofDays(1));
It thows this exception :
Exception in thread "main" java.time.temporal.UnsupportedTemporalTypeException: Unit must not have an estimated duration
Thanks in advance.
Upvotes: 2
Views: 1844
Reputation: 7753
I believe the confusion here is that the Period
object (which implements TemporalAmount
interface) can not be used in place of the Duration
object (which also implements TemporalAmount
interface).
In code:
// Below does not work
Duration d1 = Duration.from(Period.ofDays(1));
// This works fine
Duration d1 = Duration.from(Duration.ofHours(24));
This is because Duration.from
method would only accept a subset of ChronoUnit
values, that can be accurately converted to hours:
Only a subset of units are accepted by this method. The unit must either have an exact duration or be ChronoUnit.DAYS which is treated as 24 hours
From the Period definition, its value for 1-day (P1D) could be 23 or 24 hours depending on the daylight savings gap. Thus Period
has no fixed unit value for which 1-day is always 24 hours, and therefore the UnsupportedTemporalTypeException
is thrown.
From the TemporalAmount interface documentation:
Period is a date-based implementation, storing years, months and days. Duration is a time-based implementation, storing seconds and nanoseconds, but providing some access using other duration based units such as minutes, hours and fixed 24-hour days.
Upvotes: 1
Reputation: 4667
I believe @GhostCat's answer sufficiently explains how to correctly use Duration.from
and why ChronoUnit.DAYs
does not work. However, I want to clarify the source of your confusion and why you think it should work.
This sentence:
The unit must either have an exact duration or be ChronoUnit.DAYS which is treated as 24 hours.
Is mentioning ChronoUnit.DAYS
because ChronoUnit.DAYS
is an estimation set to 24 hours, and it is not an exact duration like the others. It does not mean you can simply just pass ChronoUnit.DAYS
and it will act like the TemporalAmount
of 24 hours.
Source from the docs that explains ChronoUnit.DAYS
is an estimation.
Sentence reworded to be less confusing:
The unit must have an exact duration except for ChronoUnit.DAYS which is estimated to be 24 hours.
Upvotes: 2
Reputation: 140457
Your question already mentions that this method expects a TemporalAmount. The javadoc for that interface tells us:
Framework-level interface defining an amount of time, such as "6 hours", "8 days" or "2 years and 3 months".
ChronoUnit.DAYS
isn't a temporal amount. It is simply a temporal unit of measure. But not an amount: ChronoUnit
implements TemporalUnit
, not TemporalAmount
!
In other words: "Hours" isn't an amount. "6 hours is"!
In other words: you can create a Duration
from a unit of measurement. You need to provide something that represents a specific amount of time.
Example:
Duration d = Duration.from(Duration.ofSeconds(5));
should work (as Duration implements TemporalAmount). In that example, you first define a TemporalAmount of 5 seconds, and then you can build "from" that.
Upvotes: 4