Is Duration#toDays and Duration#toDaysPart redundant?
Asked Answered
S

3

7

In Java 8, the Duration class offered the toDays method, returning a total number of days as a count of 24-hour chunks of time unrelated to calendar days.

In Java 9, the Duration class gained handy to…Part methods: toDaysPart, toHoursPart, toMinutesPart, toSecondsPart, toMillisPart, toNanosPart. I understand the need for the hours, minutes, etc. But I wonder about toDaysPart.

My question is:

➥ Will Duration#toDays and Duration#toDaysPart ever return different values for a particular Duration object?

Spiroid answered 29/3, 2021 at 20:25 Comment(1)
I believe that toSeconds() and getSeconds() are the same too. And (sidestepping) IMHO that system of methods is generally ill-named. getXxxPart would have been better, or even just getXxx() so it had been consistent with Period.getMonths() and .getDays().Sueannsuede
I
8

In Java 11, these lines of source code in OpenJDK are exactly the same.

Duration#toDays:

public long toDays() {
    return seconds / SECONDS_PER_DAY;
}

Duration#toDaysPart

public long toDaysPart(){
    return seconds / SECONDS_PER_DAY;
}

As of Java 16, no indication is made as to which is deprecated or which is not. So...keep your eyes peeled for it, is the best advice I could give you here.

Inflame answered 29/3, 2021 at 20:33 Comment(5)
I doubt deprecation is needed. I assume the toDaysPart was added on purpose, merely for consistency with the other to…Part methods. Thanks for finding the source code, and for writing the Answer.Spiroid
But they aren't quite consistent. All the to*Part methods return an int whereas the methods, sans Part, return a long - except for the days methods which returns a long in both cases. This was based on the source as of JDK 14 in the src.zip file from Oracle.Xanthein
@Xanthein Returning int versus long makes sense in context. The hours part will never be over 23, the minutes part will never be over 59, and so on. But the number of days could be very large, exceeding the limit of a int. Ex: Duration.ofDays( Integer.MAX_VALUE + 1L ).toDaysPart() = 2147483648.Spiroid
@BasilBourque Beware of the minutes with more than 60 seconds: 'Leap Second' Tonight Will Cause 61-Second MinuteBateman
@AndrewMorton Leap Second is not an issue. The point of a leap second is to harmonize between days (earth rotating on its axis) and years (earth orbiting the sun). Days are not exactly 24 hours long, and vary with the earth's rotation speed varying. A leap second adds a second in order to make the date on the calendar fit our solar time. We want to pretend that our dates are exactly 24-hours long. The leap second is a fudge-factor to maintain that pretense. So regarding this Answer, a day in java.time chronology is always the same number of seconds long, deliberately ignoring leap seconds.Spiroid
G
2

These methods don't just do the same thing; they are specified as doing the same thing in the documentation (linked in your question):

public long 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. This instance is immutable and unaffected by this method call.

Returns: the number of days in the duration, may be negative

public long toDaysPart()

Extracts the number of days in the 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. This instance is immutable and unaffected by this method call.

Returns: the number of days in the duration, may be negative

The only difference is the word "gets" vs. "extracts" in the descriptive summary. These words don't have different meanings in this context, and the rest is word-for-word identical, in particular the parts specifying what the methods return are identical. In fact, the (OpenJDK) documentation for toDaysPart was recently changed to clarify that these methods do the same thing. So yes, they are redundant.

According to the relevant issue on the issue tracker, all of the to...Part methods were added together and there wasn't any comment on the fact that toDaysPart would be redundant; so we can only speculate about the rationale for adding the redundant method.

Gaillard answered 7/8, 2021 at 10:10 Comment(3)
No need to speculate - the same PR conversation makes the rationale clear. The methods are conceptually different - the former represents the duration floored to a whole number of days; the latter represents the days "component" of the duration. Due to preconditions built into Duration they just happen to have the same value and implementation. Duplicate - yes. Redundant - in implementation. The same - no.Florri
@Dave The PR conversation explains the rationale for adding a bunch of to...Part methods, but doesn't explain the rationale for including toDaysPart among them when this method could only ever do the same thing as the existing toDays method. If there was a rationale for including the redundant method, I would expect to see some acknowledgement in the PR conversation that the proposed toDaysPart method is redundant but should be included because [rationale]. Without that, the addition of the redundant method could have been an oversight for all we know.Gaillard
It is abundantly clear if you happen to be implementing String conversion utilities across the family of interfaces from java.time. It was no oversight. It is less obvious when looking at Duration in isolation.Florri
F
0

The purpose of get(TemporalUnit) inherited from TemporalAmount, (and getSeconds() and the curiously named getNano()), are to support the extraction of the temporal components of a composed value. Duration actually only supports SECONDS and NANOS component access because a Duration is the composition of just a long seconds component with an int nanoseconds component, which together provide nanosecond resolution and representation of directed values of up to 2^63 seconds in magnitude (both positive and negative). The get_ accessors return just the named components, while the to_ methods return the composite whole value floored to the target unit. Finally the to_Part methods on Duration emulate the behaviour of the get_ methods if Duration were imagined to be composed of one instance of each ChronoUnit value. The odd one out in this virtual component access is toDaysPart. I suspect the reason for this is that while HOURS, MINUTES, SECONDS, MILLIS, MICROS and NANOS could be considered discrete and non-overlapping in terms of the components they reference, when considering DAYS as a component value it is not clear if we mean day of the week, day of the month or day of the year - all three are common conventions. Similarly MONTHS and YEARS each have variable length. So it appears the author chose to be unambiguous and consider DAYS to represent the coarsest component in that hierarchy. Personally I think its all a bit of a dog's breakfast and wondered why those two methods were identical for a while myself before reaching this conclusion.

Florri answered 7/8, 2021 at 9:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.