Duration.MAX_VALUE
Archie Cobbs
archie.cobbs at gmail.com
Thu Sep 4 22:30:14 UTC 2025
Just for the record, I think the most "correct" thing to do is fully use
Optional instead and avoid any need for MAX.
And by "correct" I mean "probably more tedious and annoying" :)
// 1. Sentinel
Optional<Duration> min = somethingStream()
.reduce(BinaryOperator.minBy(Something::compareTo));
// 2. "Forever"
void frob(Optional<Duration> optionalTimeout) {
Instant stop = optionalTimeout.map(Instant.now()::plus);
boolean done = false;
while (!done && stop.map(s -> s.compareTo(Instant.now()) <=
0).orElse(false)) {...}
}
-Archie
On Thu, Sep 4, 2025 at 5:03 PM Éamonn McManus <emcmanus at google.com> wrote:
> Two typical use cases:
>
> // 1. Sentinel
> Duration min = Duration.MAX;
> for (var foo : something()) {
> if (foo.duration().compareTo(min) < 0) {
> min = foo.duration();
> }
> }
>
> // 2. "Forever"
> void frob(Optional<Duration> optionalTimeout) {
> Duration timeout = optionalTimeout.orElse(Duration.MAX);
> Instant start = Instant.now();
> boolean done = false;
> while (!done && startTime.until(Instant.now()).compareTo(timeout) < 0)
> {...}
> }
>
> The second case illustrates why this is potentially a bit delicate. You
> better not write this:
>
> void frob(Optional<Duration> optionalTimeout) {
> Duration timeout = optionalTimeout.orElse(Duration.MAX);
> Instant deadline = Instant.now().plus(timeout); // oops
> boolean done = false;
> while (!done && Instant.now().isBefore(deadline)) {...}
> }
>
> Like Kevin, I am skeptical about Duration.MIN. If it means the most
> negative Duration, that is just Duration.MAX.negated(); and if it means the
> smallest positive Duration, that is just Duration.ofNanos(1).
>
> On Wed, 3 Sept 2025 at 18:32, Roger Riggs <roger.riggs at oracle.com> wrote:
>
>> Hi,
>>
>> I'd be interested in the range of use cases for Duration.MAX or MIN.
>>
>> But for deadlines, I think the code should compute the deadline from a
>> Duration of its choice based on the use.
>> Maybe there is a use for Duration.REALLY_BIG or _SMALL, but that ignores
>> information about the particular use that is relevant. Its just sloppy code
>> that doesn't bother to express how long is long enough to meet operational
>> parameters.
>>
>> YMMV, Roger
>>
>> On 9/3/25 8:21 PM, Kurt Alfred Kluever wrote:
>>
>> Duration.MIN is a whole 'nother bag of worms, because Durations are
>> signed (they can be positive or negative...or zero). Internally we also
>> have Durations.MIN, but it's not public ... and along with it, I left
>> myself a helpful note about naming:
>>
>> /** The minimum supported {@code Duration}, approximately -292 billion
>> years. */
>> // Note: before making this constant public, consider that "MIN" might
>> not be a great name (not
>> // everyone knows that Durations can be negative!).
>> static final Duration MIN = Duration.ofSeconds(Long.MIN_VALUE);
>>
>> This reminds me of Double.MIN_VALUE (which is the smallest _positive_
>> double value) --- we've seen Double.MIN_VALUE misused so much that we
>> introduced Doubles.MIN_POSITIVE_VALUE as a more descriptive alias. A large
>> percent of Double.MIN_VALUE users actually want the smallest possible
>> negative value, aka -Double.MAX_VALUE.
>>
>> If we introduce Duration.MIN, I hope it would not be Duration.ofNanos(1),
>> but rather Duration.ofSeconds(Long.MIN_VALUE).
>>
>> On Wed, Sep 3, 2025 at 7:59 PM ecki <ecki at zusammenkunft.net> wrote:
>>
>>> If you ask me, I don’t find it very useful, It won’t work for
>>> arithmetrics, even the APIs would have a hard time using it (how do you
>>> express the deadline) and APIs with a timeout parameter do have a good
>>> reason for it, better pick “possible” values for better self healing and
>>> unstuck of systems. In fact I would err on the smaller side in combination
>>> with expecting spurious wakeups.
>>>
>>> BTW, when you introduce MIN as well, maybe also think about min
>>> precision, min delta or such. Will it always be 1 nano?
>>>
>>> Gruß,
>>> Bernd
>>> --
>>> https://bernd.eckenfels.net
>>> ------------------------------
>>> *Von:* core-libs-dev <core-libs-dev-retn at openjdk.org> im Auftrag von
>>> Pavel Rappo <pavel.rappo at gmail.com>
>>> *Gesendet:* Donnerstag, September 4, 2025 12:41 AM
>>> *An:* Kurt Alfred Kluever <kak at google.com>
>>> *Cc:* Stephen Colebourne <scolebourne at joda.org>; core-libs-dev <
>>> core-libs-dev at openjdk.org>
>>> *Betreff:* Re: Duration.MAX_VALUE
>>>
>>> This is useful; thanks. It would be good to see more of your data.
>>>
>>> My use case is also duration which practically means **forever**. I
>>> pass it to methods that accept timeouts, and expect these methods to
>>> correctly interpret it.
>>>
>>> One example of a practical interpretation is
>>> java.util.concurrent.TimeUnit.convert(Duration). This method never
>>> overflows; instead, it caps at Long.MAX_VALUE nanoseconds, which is
>>> roughly 292 years.
>>>
>>> Would I be okay, if the proposed duration didn't reflect **forever**
>>> but instead reflected **long enough**? I think so. But it still
>>> somehow feels wrong to make it less than maximum representable value.
>>>
>>> Personally, I'm not interested in calendar arithmetic, that is, in
>>> adding or subtracting durations. Others might be, and that's okay and
>>> needs to be factored in. For better or worse, java.time made a choice
>>> to be unforgiving in regard to overflow and is very upfront about it.
>>> It's not only proposed Duration.MAX. The same thing happens if you try
>>> this
>>>
>>> Instant.MAX.toEpochMilli()
>>>
>>> I guess my point is that doing calendar arithmetic on an unknown value
>>> is probably wrong. Doing it on a known huge/edge-case value is surely
>>> wrong. So back to your data. I would be interested to see what
>>> triggers overflows for your Durations.MAX.
>>>
>>> On Wed, Sep 3, 2025 at 8:45 PM Kurt Alfred Kluever <kak at google.com>
>>> wrote:
>>> >
>>> > Hi all,
>>> >
>>> > Internally at Google, we've had a Durations.MAX constant exposed for
>>> the past 7 years. It now has about 700 usages across our depot, which I can
>>> try to categorize (at a future date).
>>> >
>>> > While I haven't performed that analysis yet, I think exposing this
>>> constant was a bit of a mistake. People seem to want to use MAX to mean
>>> "forever" (often in regards to an RPC deadline). This works fine as long as
>>> every single layer that touches the deadline is very careful about
>>> overflow. The only reasonable thing you can do with MAX is compareTo() and
>>> equals(). Attempting to do any simple math operation (e.g., now+deadline)
>>> is going to explode. Additionally, decomposing Duration.MAX explodes for
>>> any sub-second precision (e.g., toMillis()).
>>> >
>>> > As we dug into this, another proposal came up which was something like
>>> Durations.VERY_LONG. This duration would be longer than any reasonable
>>> finite duration but not long enough to cause an overflow when added to any
>>> reasonable time. E.g., a million years would probably satisfy both
>>> criteria. This would mean math operations and decompositions won't explode
>>> (well, microseconds and nanoseconds still would), and it could safely be
>>> used as a relative timeout.
>>> >
>>> > As I mentioned above, I'd be happy to try to categorize a sample of
>>> our 700 existing usages if folks think that would be useful for this
>>> proposal.
>>> >
>>> > Thanks,
>>> >
>>> > -Kurt Alfred Kluever (on behalf of Google's Java and Kotlin Ecosystem
>>> team)
>>> >
>>> > On Wed, Sep 3, 2025 at 1:53 PM Pavel Rappo <pavel.rappo at gmail.com>
>>> wrote:
>>> >>
>>> >> If I understood you correctly, you think we should also add
>>> >> Duration.MIN. If so, what use case do you envision for it? Or we add
>>> >> if purely for symmetry with Instant?
>>> >>
>>> >> On Wed, Sep 3, 2025 at 6:43 PM Pavel Rappo <pavel.rappo at gmail.com>
>>> wrote:
>>> >> >
>>> >> > On Wed, Sep 3, 2025 at 6:06 PM Stephen Colebourne <
>>> scolebourne at joda.org> wrote:
>>> >> > >
>>> >> > > Hmm, yes. Not sure why that didn't get added in Java 8!
>>> >> > > The constants would be MAX/MIN as per classes like Instant.
>>> >> > > Stephen
>>> >> >
>>> >> > I thought that naming could be tricky :) The public constant
>>> >> > Duration.ZERO and the public method isZero() are already there.
>>> >> > However, it does not preclude us from naming a new constant MAX.
>>> >
>>> >
>>> >
>>> > --
>>> > kak
>>>
>>>
>>
>> --
>> kak
>>
>>
>>
--
Archie L. Cobbs
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/core-libs-dev/attachments/20250904/337485f4/attachment-0001.htm>
More information about the core-libs-dev
mailing list