8

In the java.time framework of Java 8 and later, the Duration class says:

This class models a quantity or amount of time in terms of seconds and nanoseconds. It can be accessed using other duration-based units, such as minutes and hours. In addition, the DAYS unit can be used and is treated as exactly equal to 24 hours, thus ignoring daylight savings effects.

Yet when I call the get method and pass ChronoUnit.DAYS, an exception is thrown.

LocalTime start = LocalTime.of ( 0 , 0 , 0 ); // First moment of the day.
LocalTime stop = LocalTime.of ( 2 , 0 , 0 ); // 2 AM.

Duration duration = Duration.between ( start , stop );
long days = duration.get ( ChronoUnit.DAYS );

Exception in thread "main" java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Days

Am I misunderstanding something, or misusing the classes?

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • As far as I remember the only ``ChronoUnit`` constants that work in ``Duration.get(...)`` are ``SECONDS`` and ``NANOS`` but I never found out why. – f1sh Feb 02 '16 at 23:17
  • 1
    @f1sh Why? It is because of the inner state of `Duration` which only holds seconds and nanoseconds. The `get(TemporalField)`-method is designed to yield a **partial** amount according to the inner state. In contrast, `toDays()` tries to determine the **whole** amount converted to days on base 1d=24h. – Meno Hochschild Feb 03 '16 at 05:41
  • I have a typo in my previous comment. Instead of saying `get(TemporalField)` I wanted to say: `get(TemporalUnit)`. – Meno Hochschild Feb 03 '16 at 11:02

3 Answers3

6

Documentation for get on the Duration class.

Gets the value of the requested unit. This returns a value for each of the two supported units, SECONDS and NANOS. All other units throw an exception.

However, the Duration class has a method called toDays:

Gets the number of days in this duration. This returns the total number of days in the duration by dividing the number of seconds by 86400. This is based on the standard definition of a day as 24 hours.

kunruh
  • 874
  • 1
  • 8
  • 17
  • So the class documentation is in error, and I should file a bug report? – Basil Bourque Feb 02 '16 at 23:43
  • @BasilBourque I don't think this is a bug, but maybe just slightly confusing documentation. The overall class description just gives a summary. I'd consider method descriptions to trump the overall summary. It doesn't explicitly say *where* you can use `DAYS`, but if you read some of the other methods (like `minus`) you can use `DAYS` in those cases. – kunruh Feb 02 '16 at 23:50
  • I expended the doc quote. Sure seems to me that we should be able to get a number of days. – Basil Bourque Feb 03 '16 at 00:00
4

The get(TemporalUnit) method is unfortunately confusing and not intended for most users. To understand why, see this answer.

Java SE 9 will include a much richer set of access methods for Duration. For now, you can use toDays() to get the total number of days.

The Javadoc is not exactly wrong, but maybe not perfectly helpful. The class does have some support for days of 24 hours in the toDays(), ofDays(), plusDays() etc. It is just that the get(TemporalUnit) method is very misleadingly named (should be internalGet(TemporalUnit) or some such name).

Community
  • 1
  • 1
JodaStephen
  • 60,927
  • 15
  • 95
  • 117
0

A. It's better to replace

LocalTime start = LocalTime.of(0, 0, 0); // First moment of the day.

with

LocalTime start = LocalTime.MIN; // First moment of the day.

or with

LocalTime start = LocalTime.MIDNIGHT; // First moment of the day.

Also, the following

LocalTime stop = LocalTime.of ( 2 , 0 , 0 ); // 2 AM.

can be replaced with

LocalTime stop = LocalTime.of ( 2 , 0 ); // 2 AM.

B. The exception that you have encountered is the expected behaviour and is already documented at Duration:

This returns a value for each of the two supported units, SECONDS and NANOS. All other units throw an exception.

You can get the list of supported units using Duration#getUnits which unfortunately has been declared as a non-static function (and therefore you will have to create an arbitrary duration in order to use it):

import java.time.Duration;

public class Main {
    public static void main(String[] args) {
        Duration duration = Duration.ofDays(10);// An arbitrary duration
        System.out.println(duration.getUnits());
    }
}

Output:

[Seconds, Nanos]
Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110