Out of curiosity, how is Instants.saturatedSubtract(Instant, Duration) used?

On Wed, Oct 8, 2025 at 2:13 AM Éamonn McManus <[email protected]> wrote:
>
> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> im Auftrag von 
>> >>>> Pavel Rappo <[email protected]>
>> >>>> Gesendet: Donnerstag, September 4, 2025 12:41 AM
>> >>>> An: Kurt Alfred Kluever <[email protected]>
>> >>>> Cc: Stephen Colebourne <[email protected]>; core-libs-dev 
>> >>>> <[email protected]>
>> >>>> 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 <[email protected]> 
>> >>>> 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 <[email protected]> 
>> >>>> > 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 <[email protected]> 
>> >>>> >> wrote:
>> >>>> >> >
>> >>>> >> > On Wed, Sep 3, 2025 at 6:06 PM Stephen Colebourne 
>> >>>> >> > <[email protected]> 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
>> >>>
>> >>>

Reply via email to