11/*
2- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * This code is free software; you can redistribute it and/or modify it
2828import java .time .Duration ;
2929import java .time .Instant ;
3030import java .time .temporal .ChronoUnit ;
31- import java .time .temporal .Temporal ;
32- import java .time .temporal .TemporalAccessor ;
33- import java .time .temporal .TemporalAmount ;
3431import java .time .temporal .TemporalUnit ;
3532import java .time .temporal .UnsupportedTemporalTypeException ;
3633
3734/**
38- * A Deadline represents an instant on a {@linkplain TimeLine time line}.
35+ * An instantaneous point on the {@linkplain TimeLine time-line}.
36+ * <p>
37+ * This class is immutable and thread-safe.
38+ * <p id="overflow">
39+ * Operations that add or subtract durations to a {@code Deadline}, whether
40+ * represented as a {@link Duration} or as a {@code long} time increment (such
41+ * as seconds or nanoseconds) do not throw on numeric overflow if the resulting
42+ * {@code Deadline} would exceed {@link #MAX} or be less than {@link #MIN}.
43+ * Instead, {@code MAX} or {@code MIN} is returned, respectively. Similarly,
44+ * methods that return a duration as a {@code long} will either return
45+ * {@link Long#MAX_VALUE} or {@link Long#MIN_VALUE} if the returned quantity
46+ * would exceed the capacity of a {@code long}.
3947 */
4048public final class Deadline implements Comparable <Deadline > {
4149
@@ -49,17 +57,24 @@ private Deadline(Instant deadline) {
4957
5058
5159 /**
52- * Returns a copy of this deadline with the specified duration in nanoseconds added.
60+ * {@return a deadline with the specified duration in nanoseconds added}
5361 * <p>
5462 * This instance is immutable and unaffected by this method call.
63+ * <p>
64+ * On {@linkplain ##overflow numeric overflows}, this method will return
65+ * {@link Deadline#MAX} if the provided duration is positive,
66+ * {@link Deadline#MIN} otherwise.
5567 *
5668 * @param nanosToAdd the nanoseconds to add, positive or negative
57- * @return a {@code Deadline} based on this deadline with the specified nanoseconds added, not null
58- * @throws DateTimeException if the result exceeds the maximum or minimum deadline
59- * @throws ArithmeticException if numeric overflow occurs
6069 */
6170 public Deadline plusNanos (long nanosToAdd ) {
62- return new Deadline (deadline .plusNanos (nanosToAdd ));
71+ if (nanosToAdd == 0 ) return this ;
72+ try {
73+ return new Deadline (deadline .plusNanos (nanosToAdd ));
74+ } catch (DateTimeException | // "Instant exceeds minimum or maximum instant"
75+ ArithmeticException _) { // "long overflow"
76+ return nanosToAdd > 0 ? Deadline .MAX : Deadline .MIN ;
77+ }
6378 }
6479
6580 /**
@@ -89,92 +104,116 @@ public Deadline truncatedTo(ChronoUnit unit) {
89104 }
90105
91106 /**
92- * Returns a copy of this deadline with the specified amount subtracted.
93- * <p>
94- * This returns a {@code Deadline}, based on this one, with the specified amount subtracted.
95- * The amount is typically {@link Duration} but may be any other type implementing
96- * the {@link TemporalAmount} interface.
107+ * {@return a deadline with the specified amount subtracted from this deadline}
97108 * <p>
98109 * This instance is immutable and unaffected by this method call.
110+ * <p>
111+ * On {@linkplain ##overflow numeric overflows}, this method will return
112+ * {@link Deadline#MIN} if the provided duration is positive,
113+ * {@link Deadline#MAX} otherwise.
99114 *
100- * @param amountToSubtract the amount to subtract, not null
101- * @return a {@code Deadline} based on this deadline with the subtraction made, not null
102- * @throws DateTimeException if the subtraction cannot be made
103- * @throws ArithmeticException if numeric overflow occurs
115+ * @param duration the amount to subtract, not null
104116 */
105- public Deadline minus (TemporalAmount amountToSubtract ) {
106- return Deadline .of (deadline .minus (amountToSubtract ));
117+ public Deadline minus (Duration duration ) {
118+ if (duration .isZero ()) return this ;
119+ try {
120+ return Deadline .of (deadline .minus (duration ));
121+ } catch (DateTimeException | // "Instant exceeds minimum or maximum instant"
122+ ArithmeticException _) { // "long overflow"
123+ return duration .isPositive () ? Deadline .MIN : Deadline .MAX ;
124+ }
107125 }
108126
109127 /**
110- * Returns a copy of this deadline with the specified amount added.
128+ * {@return a deadline with the specified amount added to this deadline}
111129 * <p>
112130 * This returns a {@code Deadline}, based on this one, with the amount
113131 * in terms of the unit added. If it is not possible to add the amount, because the
114132 * unit is not supported or for some other reason, an exception is thrown.
115133 * <p>
116134 * This instance is immutable and unaffected by this method call.
135+ * <p>
136+ * On {@linkplain ##overflow numeric overflows}, this method will return
137+ * {@link Deadline#MAX} if the provided amount is positive,
138+ * {@link Deadline#MIN} otherwise.
117139 *
118140 * @see Instant#plus(long, TemporalUnit)
119141 *
120142 * @param amountToAdd the amount of the unit to add to the result, may be negative
121143 * @param unit the unit of the amount to add, not null
122- * @return a {@code Deadline} based on this deadline with the specified amount added, not null
123- * @throws DateTimeException if the addition cannot be made
124144 * @throws UnsupportedTemporalTypeException if the unit is not supported
125- * @throws ArithmeticException if numeric overflow occurs
126145 */
127146 public Deadline plus (long amountToAdd , TemporalUnit unit ) {
128147 if (amountToAdd == 0 ) return this ;
129- return Deadline .of (deadline .plus (amountToAdd , unit ));
148+ try {
149+ return Deadline .of (deadline .plus (amountToAdd , unit ));
150+ } catch (DateTimeException | // "Instant exceeds minimum or maximum instant"
151+ ArithmeticException _) { // "long overflow"
152+ return amountToAdd > 0 ? Deadline .MAX : Deadline .MIN ;
153+ }
130154 }
131155
132156 /**
133- * Returns a copy of this deadline with the specified duration in seconds added.
157+ * {@return a deadline with the specified duration in seconds added to this deadline}
134158 * <p>
135159 * This instance is immutable and unaffected by this method call.
160+ * <p>
161+ * On {@linkplain ##overflow numeric overflows}, this method will return
162+ * {@link Deadline#MAX} if the provided duration is positive,
163+ * {@link Deadline#MIN} otherwise.
136164 *
137165 * @param secondsToAdd the seconds to add, positive or negative
138- * @return a {@code Deadline} based on this deadline with the specified seconds added, not null
139- * @throws DateTimeException if the result exceeds the maximum or minimum deadline
140- * @throws ArithmeticException if numeric overflow occurs
141166 */
142167 public Deadline plusSeconds (long secondsToAdd ) {
143168 if (secondsToAdd == 0 ) return this ;
144- return Deadline .of (deadline .plusSeconds (secondsToAdd ));
169+ try {
170+ return Deadline .of (deadline .plusSeconds (secondsToAdd ));
171+ } catch (DateTimeException | // "Instant exceeds minimum or maximum instant"
172+ ArithmeticException _) { // "long overflow"
173+ return secondsToAdd > 0 ? Deadline .MAX : Deadline .MIN ;
174+ }
145175 }
146176
147177 /**
148- * Returns a copy of this deadline with the specified duration in milliseconds added.
178+ * {@return a deadline with the specified duration in milliseconds added to this deadline}
149179 * <p>
150180 * This instance is immutable and unaffected by this method call.
181+ * <p>
182+ * On {@linkplain ##overflow numeric overflows}, this method will return
183+ * {@link Deadline#MAX} if the provided duration is positive,
184+ * {@link Deadline#MIN} otherwise.
151185 *
152186 * @param millisToAdd the milliseconds to add, positive or negative
153- * @return a {@code Deadline} based on this deadline with the specified milliseconds added, not null
154- * @throws DateTimeException if the result exceeds the maximum or minimum deadline
155- * @throws ArithmeticException if numeric overflow occurs
156187 */
157188 public Deadline plusMillis (long millisToAdd ) {
158189 if (millisToAdd == 0 ) return this ;
159- return Deadline .of (deadline .plusMillis (millisToAdd ));
190+ try {
191+ return Deadline .of (deadline .plusMillis (millisToAdd ));
192+ } catch (DateTimeException | // "Instant exceeds minimum or maximum instant"
193+ ArithmeticException _) { // "long overflow"
194+ return millisToAdd > 0 ? Deadline .MAX : Deadline .MIN ;
195+ }
160196 }
161197
162198 /**
163- * Returns a copy of this deadline with the specified amount added.
164- * <p>
165- * This returns a {@code Deadline}, based on this one, with the specified amount added.
166- * The amount is typically {@link Duration} but may be any other type implementing
167- * the {@link TemporalAmount} interface.
199+ * {@return a deadline with the specified duration added to this deadline}
168200 * <p>
169201 * This instance is immutable and unaffected by this method call.
202+ * <p>
203+ * On {@linkplain ##overflow numeric overflows}, this method will return
204+ * {@link Deadline#MAX} if the provided duration is positive,
205+ * {@link Deadline#MIN} otherwise.
170206 *
171- * @param amountToAdd the amount to add, not null
172- * @return a {@code Deadline} based on this deadline with the addition made, not null
173- * @throws DateTimeException if the addition cannot be made
174- * @throws ArithmeticException if numeric overflow occurs
207+ * @param duration the duration to add, not null
175208 */
176- public Deadline plus (TemporalAmount amountToAdd ) {
177- return Deadline .of (deadline .plus (amountToAdd ));
209+ public Deadline plus (Duration duration ) {
210+ if (duration .isZero ()) return this ;
211+ try {
212+ return Deadline .of (deadline .plus (duration ));
213+ } catch (DateTimeException | // "Instant exceeds minimum or maximum instant"
214+ ArithmeticException _) { // "long overflow"
215+ return duration .isPositive () ? Deadline .MAX : Deadline .MIN ;
216+ }
178217 }
179218
180219 /**
@@ -188,16 +227,24 @@ public Deadline plus(TemporalAmount amountToAdd) {
188227 * complete units between the two deadlines.
189228 * <p>
190229 * This instance is immutable and unaffected by this method call.
230+ * <p>
231+ * On {@linkplain ##overflow numeric overflows}, this method will return
232+ * {@link Long#MAX_VALUE} if the current deadline is before the provided end
233+ * deadline, {@link Long#MIN_VALUE} otherwise.
191234 *
192235 * @param endExclusive the end deadline, exclusive
193236 * @param unit the unit to measure the amount in, not null
194237 * @return the amount of time between this deadline and the end deadline
195- * @throws DateTimeException if the amount cannot be calculated
196238 * @throws UnsupportedTemporalTypeException if the unit is not supported
197- * @throws ArithmeticException if numeric overflow occurs
198239 */
199240 public long until (Deadline endExclusive , TemporalUnit unit ) {
200- return deadline .until (endExclusive .deadline , unit );
241+ try {
242+ return deadline .until (endExclusive .deadline , unit );
243+ } catch (DateTimeException | // "Instant exceeds minimum or maximum instant"
244+ ArithmeticException _) { // "long overflow"
245+ int delta = compareTo (endExclusive );
246+ return delta < 0 ? Long .MAX_VALUE : Long .MIN_VALUE ;
247+ }
201248 }
202249
203250 /**
@@ -266,10 +313,13 @@ static Deadline of(Instant instant) {
266313 * @param startInclusive the start deadline, inclusive, not null
267314 * @param endExclusive the end deadline, exclusive, not null
268315 * @return a {@code Duration}, not null
269- * @throws DateTimeException if the seconds between the deadline cannot be obtained
270- * @throws ArithmeticException if the calculation exceeds the capacity of {@code Duration}
271316 */
272317 public static Duration between (Deadline startInclusive , Deadline endExclusive ) {
318+ if (startInclusive .equals (endExclusive )) return Duration .ZERO ;
319+ // `Deadline` works with `Instant` under the hood.
320+ // Delta between `Instant.MIN` and `Instant.MAX` fits in a `Duration`.
321+ // Hence, we should never receive a numeric overflow while calculating the delta between two deadlines.
273322 return Duration .between (startInclusive .deadline , endExclusive .deadline );
274323 }
324+
275325}
0 commit comments