I want to get a java.time.Duration
instance representing the duration of 3 years,
and i found 2 ways to do it (see code below).
public static void main(String[] args) {
Duration d1 = Duration.of(3, ChronoUnit.YEARS); //Runtime Exception
Duration d2 = ChronoUnit.YEARS.getDuration().multipliedBy(3);
System.out.println("d2="+d2.toDays()); //OUTPUT: d2=1095
}
The first way, d1
, throws the following Exception at runtime:
Exception in thread "main" java.time.temporal.UnsupportedTemporalTypeException: Unit must not have an estimated duration at java.time.Duration.plus(Unknown Source) at java.time.Duration.of(Unknown Source) at mod7.vehicalc.Test.main(Test.java:26)
The second way, d2
, works as expected.
What is the reason for this difference?
The javadoc for
ChronoUnit#getDuration()
statesThat is,
YEARS
is aor 31556952 seconds. This is just an estimation.
Duration.of(..)
expects a unit with an exact time value.A
Duration
is a time-based amount of time.A
Period
is a date-based amount of time.Given that years are clearly date-based and not time-based, you need to be using
Period
. (There is no "recurrance" aspect toPeriod
).The estimated duration method on
ChronoUnit
is primarily intended for the purpose of sorting units, ie. being able to say that a year is generally longer than a month. It is not intended to be the basis of mathematical calculations or creating a largerDuration
. In particular, if you use aPeriod
then addition to aLocalDate
orZonedDateTime
will result in the correct answer. If you use aDuration
then you will probably get an unexpected/wrong answer.