Duration.MAX_VALUE

Éamonn McManus emcmanus at google.com
Wed Oct 8 00:13:24 UTC 2025


Yes, we have utility classes Instants and Durations, and Instants includes
methods Instants.saturatedAdd(Instant, Duration) and
Instants.saturatedSubtract(Instant, Duration). Each has a modest number of
uses in the codebase, about three orders of magnitude less than the number
of classes that reference Instant or Duration.

On Tue, 7 Oct 2025 at 14:18, Pavel Rappo <pavel.rappo at gmail.com> wrote:

> Éamonn, Kurt,
>
> Is there any saturating arithmetic for instant + duration in your code
> base?
>
>
>
> On Fri, Sep 5, 2025 at 8:58 PM Éamonn McManus <emcmanus at google.com> wrote:
> >
> > As promised, Kurt and I have examined some of the uses of our
> Durations.MAX constant. This is a summary of what we see in a random sample
> of 30 out of about 700 usages in Google's (giant) codebase.
> >
> > First, about half of the usages specifically concern deadlines. Many of
> them involve a method that sets an RPC deadline and where it is explicitly
> documented that you should use Durations.MAX to mean no deadline (or
> equivalently, infinite deadline).
> >
> > Several other usages concern deadline-adjacent concepts such as
> time-to-live or cache expiration delay.
> >
> > A number of usages specifically compare a Duration against Durations.MAX
> to recognize the "infinite duration" value.
> >
> > One usage uses our internal Sleeper interface to do
> sleeper.sleep(Durations.MAX), for an indefinite sleep (until interrupted).
> >
> > In a couple of places, there is a maximum allowed Duration for some
> operation, and a user-supplied Duration value is capped by this maximum.
> When no maximum is needed, the cap is Durations.MAX. This is similar to the
> "sentinel" use case I mentioned earlier.
> >
> > One case is using Durations.MAX in a test, to ensure that a function
> works correctly for all Duration values including the largest one. It is
> testing a Kotlin extension function that allows you to write e.g. 5.minutes:
> >
> >     val n = Durations.MAX.toMinutes()
> >
> >     assertThat(n.minutes).isEqualTo(Duration.ofMinutes(n))
> >
> >     assertFailsWith<ArithmeticException> { (n + 1).minutes }
> >
> >
> > In summary, I think the most interesting use cases fall into these
> categories:
> >
> > to express an effectively-infinite Duration, possibly accompanied by
> special-case logic to optimize the exact value Durations.MAX;
> >
> > to express the absence of an optional cap on a user-supplied Duration
> value;
> >
> > to test that code works correctly even with extreme Duration values.
> >
> >
> > Of these, the first is potentially fragile because of the overflow
> problems we discussed. The other two seem unproblematic, though.
> >
> >
> >
> > On Thu, 4 Sept 2025 at 15:02, É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
> >>>
> >>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/core-libs-dev/attachments/20251007/a9da9caf/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 5281 bytes
Desc: S/MIME Cryptographic Signature
URL: <https://mail.openjdk.org/pipermail/core-libs-dev/attachments/20251007/a9da9caf/smime-0001.p7s>


More information about the core-libs-dev mailing list