From 98bb980c5354021376ac0223a8946fb3a99c94cc Mon Sep 17 00:00:00 2001 From: Chip Kent Date: Mon, 20 May 2024 13:18:26 -0600 Subject: [PATCH 01/11] Added functions to multiply durations and periods. --- .../java/io/deephaven/time/DateTimeUtils.java | 61 +++++++++++++++++++ .../io/deephaven/time/TestDateTimeUtils.java | 25 ++++++++ 2 files changed, 86 insertions(+) diff --git a/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java b/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java index 934ebcc6c0a..ea06842f56e 100644 --- a/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java +++ b/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java @@ -1871,6 +1871,67 @@ public static long minus(@Nullable final ZonedDateTime dateTime1, @Nullable fina return checkUnderflowMinus(epochNanos(dateTime1), epochNanos(dateTime2), true); } + /** + * Multiply a duration by a scalar. + * + * @param duration the duration to multiply + * @param scalar the scalar to multiply by + * @return {@code null} if either input is {@code null}; otherwise the duration multiplied by the scalar + */ + public static Duration multiply(final Duration duration, final long scalar) { + if (duration == null || scalar == NULL_LONG) { + return null; + } + + return duration.multipliedBy(scalar); + } + + /** + * Multiply a duration by a scalar. + * + * @param duration the duration to multiply + * @param scalar the scalar to multiply by + * @return {@code null} if either input is {@code null}; otherwise the duration multiplied by the scalar + */ + public static Duration multiply(final long scalar, final Duration duration) { + if (duration == null || scalar == NULL_LONG) { + return null; + } + + return duration.multipliedBy(scalar); + } + + /** + * Multiply a period by a scalar. + * + * @param period the period to multiply + * @param scalar the scalar to multiply by + * @return {@code null} if either input is {@code null}; otherwise the period multiplied by the scalar + */ + public static Period multiply(final Period period, final int scalar) { + if (period == null || scalar == NULL_INT) { + return null; + } + + return period.multipliedBy(scalar); + } + + /** + * Multiply a period by a scalar. + * + * @param period the period to multiply + * @param scalar the scalar to multiply by + * @return {@code null} if either input is {@code null}; otherwise the period multiplied by the scalar + */ + public static Period multiply(final int scalar, final Period period) { + if (period == null || scalar == NULL_INT) { + return null; + } + + return period.multipliedBy(scalar); + } + + /** * Returns the difference in nanoseconds between two instant values. * diff --git a/engine/time/src/test/java/io/deephaven/time/TestDateTimeUtils.java b/engine/time/src/test/java/io/deephaven/time/TestDateTimeUtils.java index 68bf3c51a26..b3d583b3e98 100644 --- a/engine/time/src/test/java/io/deephaven/time/TestDateTimeUtils.java +++ b/engine/time/src/test/java/io/deephaven/time/TestDateTimeUtils.java @@ -2347,6 +2347,31 @@ public void testMinus() { } + public void testMultiply() { + final Period p = Period.ofDays(3); + final Duration d = Duration.ofNanos(123456789L); + + TestCase.assertEquals(Period.ofDays(6), DateTimeUtils.multiply(p, 2)); + TestCase.assertEquals(Period.ofDays(9), DateTimeUtils.multiply(p, 3)); + TestCase.assertEquals(Period.ofDays(3), DateTimeUtils.multiply(p, 1)); + TestCase.assertEquals(Period.ofDays(0), DateTimeUtils.multiply(p, 0)); + TestCase.assertEquals(Period.ofDays(-3), DateTimeUtils.multiply(p, -1)); + TestCase.assertEquals(Period.ofDays(-6), DateTimeUtils.multiply(p, -2)); + TestCase.assertEquals(Period.ofDays(-9), DateTimeUtils.multiply(p, -3)); + TestCase.assertNull(DateTimeUtils.multiply((Period) null, 3)); + TestCase.assertNull(DateTimeUtils.multiply(p, NULL_INT)); + + TestCase.assertEquals(Duration.ofNanos(246913578L), DateTimeUtils.multiply(d, 2)); + TestCase.assertEquals(Duration.ofNanos(370370367L), DateTimeUtils.multiply(d, 3)); + TestCase.assertEquals(Duration.ofNanos(123456789L), DateTimeUtils.multiply(d, 1)); + TestCase.assertEquals(Duration.ofNanos(0), DateTimeUtils.multiply(d, 0)); + TestCase.assertEquals(Duration.ofNanos(-123456789L), DateTimeUtils.multiply(d, -1)); + TestCase.assertEquals(Duration.ofNanos(-246913578L), DateTimeUtils.multiply(d, -2)); + TestCase.assertEquals(Duration.ofNanos(-370370367L), DateTimeUtils.multiply(d, -3)); + TestCase.assertNull(DateTimeUtils.multiply((Duration) null, 3)); + TestCase.assertNull(DateTimeUtils.multiply(d, NULL_LONG)); + } + public void testDiffNanos() { final Instant i1 = DateTimeUtils.epochNanosToInstant(12345678987654321L); final Instant i2 = DateTimeUtils.epochNanosToInstant(98765432123456789L); From 655f4d0221dec8af5f97e200d008f0f5e83f1c9f Mon Sep 17 00:00:00 2001 From: Chip Kent Date: Wed, 22 May 2024 13:07:27 -0600 Subject: [PATCH 02/11] Add durations. Add periods. Subtract durations. Subtract periods. Multiply durations by doubles. Multiply periods by longs. Divide durations. --- .../java/io/deephaven/time/DateTimeUtils.java | 186 +++++++++++++++++- .../io/deephaven/time/TestDateTimeUtils.java | 151 ++++++++++++++ 2 files changed, 331 insertions(+), 6 deletions(-) diff --git a/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java b/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java index ea06842f56e..9a8ba781f85 100644 --- a/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java +++ b/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java @@ -24,8 +24,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import static io.deephaven.util.QueryConstants.NULL_INT; -import static io.deephaven.util.QueryConstants.NULL_LONG; +import static io.deephaven.util.QueryConstants.*; import static java.time.format.DateTimeFormatter.*; /** @@ -1652,6 +1651,44 @@ public static ZonedDateTime plus(@Nullable final ZonedDateTime dateTime, @Nullab } } + /** + * Adds two durations. + * + * @param duration1 first duration + * @param duration2 second duration + * @return {@code null} if either input is {@code null}; otherwise the sum of the two durations + */ + public static Duration plus(@Nullable final Duration duration1, @Nullable final Duration duration2) { + if (duration1 == null || duration2 == null) { + return null; + } + + try { + return duration1.plus(duration2); + } catch (Exception ex) { + throw new DateTimeOverflowException(ex); + } + } + + /** + * Adds two periods. + * + * @param period1 first period + * @param period2 second period + * @return {@code null} if either input is {@code null}; otherwise the sum of the two periods + */ + public static Period plus(@Nullable final Period period1, @Nullable final Period period2) { + if (period1 == null || period2 == null) { + return null; + } + + try { + return period1.plus(period2); + } catch (Exception ex) { + throw new DateTimeOverflowException(ex); + } + } + /** * Subtracts days from a {@link LocalDate}. * @@ -1871,6 +1908,44 @@ public static long minus(@Nullable final ZonedDateTime dateTime1, @Nullable fina return checkUnderflowMinus(epochNanos(dateTime1), epochNanos(dateTime2), true); } + /** + * Subtracts two durations. + * + * @param duration1 first duration + * @param duration2 second duration + * @return {@code null} if either input is {@code null}; otherwise the difference of the two durations + */ + public static Duration minus(@Nullable final Duration duration1, @Nullable final Duration duration2) { + if (duration1 == null || duration2 == null) { + return null; + } + + try { + return duration1.minus(duration2); + } catch (Exception ex) { + throw new DateTimeOverflowException(ex); + } + } + + /** + * Subtracts two periods. + * + * @param period1 first period + * @param period2 second period + * @return {@code null} if either input is {@code null}; otherwise the difference of the two periods + */ + public static Period minus(@Nullable final Period period1, @Nullable final Period period2) { + if (period1 == null || period2 == null) { + return null; + } + + try { + return period1.minus(period2); + } catch (Exception ex) { + throw new DateTimeOverflowException(ex); + } + } + /** * Multiply a duration by a scalar. * @@ -1894,11 +1969,43 @@ public static Duration multiply(final Duration duration, final long scalar) { * @return {@code null} if either input is {@code null}; otherwise the duration multiplied by the scalar */ public static Duration multiply(final long scalar, final Duration duration) { - if (duration == null || scalar == NULL_LONG) { + return multiply(duration, scalar); + } + + /** + * Multiply a duration by a scalar. + * + * @param duration the duration to multiply + * @param scalar the scalar to multiply by + * @return {@code null} if either input is {@code null}; otherwise the duration multiplied by the scalar + */ + public static Duration multiply(final Duration duration, final double scalar) { + if (duration == null || scalar == NULL_DOUBLE) { return null; } - return duration.multipliedBy(scalar); + if(Double.isNaN(scalar)) { + throw new DateTimeOverflowException("Scalar value is NaN"); + } + + final double product = duration.toNanos() * scalar; + + if(product > Long.MAX_VALUE || product < Long.MIN_VALUE) { + throw new DateTimeOverflowException("Product value is too large to be cast to a long"); + } + + return Duration.ofNanos((long) product); + } + + /** + * Multiply a duration by a scalar. + * + * @param duration the duration to multiply + * @param scalar the scalar to multiply by + * @return {@code null} if either input is {@code null}; otherwise the duration multiplied by the scalar + */ + public static Duration multiply(final double scalar, final Duration duration) { + return multiply(duration, scalar); } /** @@ -1924,13 +2031,80 @@ public static Period multiply(final Period period, final int scalar) { * @return {@code null} if either input is {@code null}; otherwise the period multiplied by the scalar */ public static Period multiply(final int scalar, final Period period) { - if (period == null || scalar == NULL_INT) { + return multiply(period, scalar); + } + + /** + * Multiply a period by a scalar. + * + * @param period the period to multiply + * @param scalar the scalar to multiply by + * @return {@code null} if either input is {@code null}; otherwise the period multiplied by the scalar + */ + public static Period multiply(final Period period, final long scalar) { + if (period == null || scalar == NULL_LONG) { return null; } - return period.multipliedBy(scalar); + if(scalar > Integer.MAX_VALUE || scalar < Integer.MIN_VALUE) { + throw new DateTimeOverflowException("Scalar value is too large to be cast to an int"); + } + + return period.multipliedBy((int) scalar); + } + + /** + * Multiply a period by a scalar. + * + * @param period the period to multiply + * @param scalar the scalar to multiply by + * @return {@code null} if either input is {@code null}; otherwise the period multiplied by the scalar + */ + public static Period multiply(final long scalar, final Period period) { + return multiply(period, scalar); } + /** + * Divide a duration by a scalar. + * + * @param duration the duration to divide + * @param scalar the scalar to divide by + * @return {@code null} if either input is {@code null}; otherwise the duration divide by the scalar + */ + public static Duration divide(final Duration duration, final long scalar) { + if (duration == null || scalar == NULL_LONG) { + return null; + } + + if(scalar == 0) { + throw new DateTimeOverflowException("Scalar value is zero"); + } + + return duration.dividedBy(scalar); + } + + /** + * Divide a duration by a scalar. + * + * @param duration the duration to divide + * @param scalar the scalar to divide by + * @return {@code null} if either input is {@code null}; otherwise the duration divide by the scalar + */ + public static Duration divide(final Duration duration, final double scalar) { + if (duration == null || scalar == NULL_DOUBLE) { + return null; + } + + if(Double.isNaN(scalar)) { + throw new DateTimeOverflowException("Scalar value is NaN"); + } + + if(scalar == 0) { + throw new DateTimeOverflowException("Scalar value is zero"); + } + + return Duration.ofNanos((long) (duration.toNanos() / scalar)); + } /** * Returns the difference in nanoseconds between two instant values. diff --git a/engine/time/src/test/java/io/deephaven/time/TestDateTimeUtils.java b/engine/time/src/test/java/io/deephaven/time/TestDateTimeUtils.java index b3d583b3e98..bbb61f2f505 100644 --- a/engine/time/src/test/java/io/deephaven/time/TestDateTimeUtils.java +++ b/engine/time/src/test/java/io/deephaven/time/TestDateTimeUtils.java @@ -2012,6 +2012,40 @@ public void testPlusLocalDate() { // ok } } + + public void testPlusDuration() { + final Duration d1 = Duration.ofSeconds(1); + final Duration d2 = Duration.ofSeconds(2); + final Duration d3 = Duration.ofSeconds(3); + TestCase.assertEquals(d3, DateTimeUtils.plus(d1, d2)); + TestCase.assertEquals(d3, DateTimeUtils.plus(d2, d1)); + TestCase.assertNull(DateTimeUtils.plus(d1, null)); + TestCase.assertNull(DateTimeUtils.plus((Duration) null, d2)); + + try { + DateTimeUtils.plus(d1, Duration.ofSeconds(Long.MAX_VALUE)); + TestCase.fail("This should have overflowed"); + } catch (DateTimeUtils.DateTimeOverflowException e) { + // ok + } + } + + public void testPlusPeriod() { + final Period d1 = Period.ofDays(1); + final Period d2 = Period.ofDays(2); + final Period d3 = Period.ofDays(3); + TestCase.assertEquals(d3, DateTimeUtils.plus(d1, d2)); + TestCase.assertEquals(d3, DateTimeUtils.plus(d2, d1)); + TestCase.assertNull(DateTimeUtils.plus(d1, null)); + TestCase.assertNull(DateTimeUtils.plus((Period) null, d2)); + + try { + DateTimeUtils.plus(d1, Period.ofDays(Integer.MAX_VALUE)); + TestCase.fail("This should have overflowed"); + } catch (DateTimeUtils.DateTimeOverflowException e) { + // ok + } + } public void testPlus() { final Instant instant = DateTimeUtils.parseInstant("2010-01-01T12:13:14.999123456 JP"); @@ -2188,6 +2222,38 @@ public void testMinusLocalDate() { } } + public void testMinusDuration() { + final Duration d1 = Duration.ofSeconds(3); + final Duration d2 = Duration.ofSeconds(1); + TestCase.assertEquals(Duration.ofSeconds(2), DateTimeUtils.minus(d1, d2)); + TestCase.assertEquals(Duration.ofSeconds(-2), DateTimeUtils.minus(d2, d1)); + TestCase.assertNull(DateTimeUtils.minus(d1, null)); + TestCase.assertNull(DateTimeUtils.minus((Duration) null, d2)); + + try { + DateTimeUtils.minus(d1, Duration.ofSeconds(Long.MIN_VALUE)); + TestCase.fail("This should have overflowed"); + } catch (DateTimeUtils.DateTimeOverflowException e) { + // ok + } + } + + public void testMinusPeriod() { + final Period d1 = Period.ofDays(3); + final Period d2 = Period.ofDays(1); + TestCase.assertEquals(Period.ofDays(2), DateTimeUtils.minus(d1, d2)); + TestCase.assertEquals(Period.ofDays(-2), DateTimeUtils.minus(d2, d1)); + TestCase.assertNull(DateTimeUtils.minus(d1, null)); + TestCase.assertNull(DateTimeUtils.minus((Period) null, d2)); + + try { + DateTimeUtils.minus(d1, Period.ofDays(Integer.MIN_VALUE)); + TestCase.fail("This should have overflowed"); + } catch (DateTimeUtils.DateTimeOverflowException e) { + // ok + } + } + public void testMinus() { final Instant instant1 = DateTimeUtils.parseInstant("2010-01-01T12:13:14.999123456 JP"); final Instant instant2 = DateTimeUtils.parseInstant("2010-01-01T13:13:14.999123456 JP"); @@ -2352,6 +2418,7 @@ public void testMultiply() { final Duration d = Duration.ofNanos(123456789L); TestCase.assertEquals(Period.ofDays(6), DateTimeUtils.multiply(p, 2)); + TestCase.assertEquals(Period.ofDays(6), DateTimeUtils.multiply(2, p)); TestCase.assertEquals(Period.ofDays(9), DateTimeUtils.multiply(p, 3)); TestCase.assertEquals(Period.ofDays(3), DateTimeUtils.multiply(p, 1)); TestCase.assertEquals(Period.ofDays(0), DateTimeUtils.multiply(p, 0)); @@ -2361,7 +2428,26 @@ public void testMultiply() { TestCase.assertNull(DateTimeUtils.multiply((Period) null, 3)); TestCase.assertNull(DateTimeUtils.multiply(p, NULL_INT)); + TestCase.assertEquals(Period.ofDays(6), DateTimeUtils.multiply(p, 2L)); + TestCase.assertEquals(Period.ofDays(6), DateTimeUtils.multiply(2L, p)); + TestCase.assertEquals(Period.ofDays(9), DateTimeUtils.multiply(p, 3L)); + TestCase.assertEquals(Period.ofDays(3), DateTimeUtils.multiply(p, 1L)); + TestCase.assertEquals(Period.ofDays(0), DateTimeUtils.multiply(p, 0L)); + TestCase.assertEquals(Period.ofDays(-3), DateTimeUtils.multiply(p, -1L)); + TestCase.assertEquals(Period.ofDays(-6), DateTimeUtils.multiply(p, -2L)); + TestCase.assertEquals(Period.ofDays(-9), DateTimeUtils.multiply(p, -3L)); + TestCase.assertNull(DateTimeUtils.multiply((Period) null, 3L)); + TestCase.assertNull(DateTimeUtils.multiply(p, NULL_LONG)); + + try{ + DateTimeUtils.multiply(p, Long.MAX_VALUE); + TestCase.fail("This should have overflowed"); + } catch (DateTimeUtils.DateTimeOverflowException e) { + // ok + } + TestCase.assertEquals(Duration.ofNanos(246913578L), DateTimeUtils.multiply(d, 2)); + TestCase.assertEquals(Duration.ofNanos(246913578L), DateTimeUtils.multiply(2, d)); TestCase.assertEquals(Duration.ofNanos(370370367L), DateTimeUtils.multiply(d, 3)); TestCase.assertEquals(Duration.ofNanos(123456789L), DateTimeUtils.multiply(d, 1)); TestCase.assertEquals(Duration.ofNanos(0), DateTimeUtils.multiply(d, 0)); @@ -2370,6 +2456,71 @@ public void testMultiply() { TestCase.assertEquals(Duration.ofNanos(-370370367L), DateTimeUtils.multiply(d, -3)); TestCase.assertNull(DateTimeUtils.multiply((Duration) null, 3)); TestCase.assertNull(DateTimeUtils.multiply(d, NULL_LONG)); + + TestCase.assertEquals(Duration.ofNanos(246913578L), DateTimeUtils.multiply(d, 2.0)); + TestCase.assertEquals(Duration.ofNanos(246913578L), DateTimeUtils.multiply(2.0, d)); + TestCase.assertNull(DateTimeUtils.multiply((Duration) null, 3.0)); + TestCase.assertNull(DateTimeUtils.multiply(d, NULL_DOUBLE)); + + try{ + DateTimeUtils.multiply(d, Double.NaN); + TestCase.fail("This should have excepted"); + } catch (DateTimeUtils.DateTimeOverflowException e) { + // ok + } + + try{ + DateTimeUtils.multiply(d, Double.POSITIVE_INFINITY); + TestCase.fail("This should have excepted"); + } catch (DateTimeUtils.DateTimeOverflowException e) { + // ok + } + + try{ + DateTimeUtils.multiply(d, Double.NEGATIVE_INFINITY); + TestCase.fail("This should have excepted"); + } catch (DateTimeUtils.DateTimeOverflowException e) { + // ok + } + } + + public void testDivideDuration() { + final Duration d = Duration.ofNanos(123456789L); + + TestCase.assertEquals(Duration.ofNanos(61728394L), DateTimeUtils.divide(d, 2)); + TestCase.assertEquals(Duration.ofNanos(123456789L), DateTimeUtils.divide(d, 1)); + TestCase.assertEquals(Duration.ofNanos(-123456789L), DateTimeUtils.divide(d, -1)); + TestCase.assertEquals(Duration.ofNanos(-61728394L), DateTimeUtils.divide(d, -2)); + TestCase.assertNull(DateTimeUtils.divide((Duration) null, 3)); + TestCase.assertNull(DateTimeUtils.divide(d, NULL_LONG)); + + try{ + DateTimeUtils.divide(d, 0); + TestCase.fail("This should have excepted"); + } catch (DateTimeUtils.DateTimeOverflowException e) { + // ok + } + + TestCase.assertEquals(Duration.ofNanos(61728394L), DateTimeUtils.divide(d, 2.0)); + TestCase.assertEquals(Duration.ofNanos(0L), DateTimeUtils.divide(d, POS_INFINITY_DOUBLE)); + TestCase.assertEquals(Duration.ofNanos(0L), DateTimeUtils.divide(d, NEG_INFINITY_DOUBLE)); + TestCase.assertNull(DateTimeUtils.divide((Duration) null, 3.0)); + TestCase.assertNull(DateTimeUtils.divide(d, NULL_DOUBLE)); + + try{ + DateTimeUtils.divide(d, 0.0); + TestCase.fail("This should have excepted"); + } catch (DateTimeUtils.DateTimeOverflowException e) { + // ok + } + + try{ + DateTimeUtils.divide(d, Double.NaN); + TestCase.fail("This should have excepted"); + } catch (DateTimeUtils.DateTimeOverflowException e) { + // ok + } + } public void testDiffNanos() { From 7130dcc59eaf7e09f6f67d8eceeba81d7e03d932 Mon Sep 17 00:00:00 2001 From: Chip Kent Date: Wed, 22 May 2024 13:08:42 -0600 Subject: [PATCH 03/11] Spotless --- .../java/io/deephaven/time/DateTimeUtils.java | 16 ++++++++-------- .../io/deephaven/time/TestDateTimeUtils.java | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java b/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java index 9a8ba781f85..94f56bca616 100644 --- a/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java +++ b/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java @@ -1673,7 +1673,7 @@ public static Duration plus(@Nullable final Duration duration1, @Nullable final /** * Adds two periods. * - * @param period1 first period + * @param period1 first period * @param period2 second period * @return {@code null} if either input is {@code null}; otherwise the sum of the two periods */ @@ -1930,7 +1930,7 @@ public static Duration minus(@Nullable final Duration duration1, @Nullable final /** * Subtracts two periods. * - * @param period1 first period + * @param period1 first period * @param period2 second period * @return {@code null} if either input is {@code null}; otherwise the difference of the two periods */ @@ -1984,13 +1984,13 @@ public static Duration multiply(final Duration duration, final double scalar) { return null; } - if(Double.isNaN(scalar)) { + if (Double.isNaN(scalar)) { throw new DateTimeOverflowException("Scalar value is NaN"); } final double product = duration.toNanos() * scalar; - if(product > Long.MAX_VALUE || product < Long.MIN_VALUE) { + if (product > Long.MAX_VALUE || product < Long.MIN_VALUE) { throw new DateTimeOverflowException("Product value is too large to be cast to a long"); } @@ -2046,7 +2046,7 @@ public static Period multiply(final Period period, final long scalar) { return null; } - if(scalar > Integer.MAX_VALUE || scalar < Integer.MIN_VALUE) { + if (scalar > Integer.MAX_VALUE || scalar < Integer.MIN_VALUE) { throw new DateTimeOverflowException("Scalar value is too large to be cast to an int"); } @@ -2076,7 +2076,7 @@ public static Duration divide(final Duration duration, final long scalar) { return null; } - if(scalar == 0) { + if (scalar == 0) { throw new DateTimeOverflowException("Scalar value is zero"); } @@ -2095,11 +2095,11 @@ public static Duration divide(final Duration duration, final double scalar) { return null; } - if(Double.isNaN(scalar)) { + if (Double.isNaN(scalar)) { throw new DateTimeOverflowException("Scalar value is NaN"); } - if(scalar == 0) { + if (scalar == 0) { throw new DateTimeOverflowException("Scalar value is zero"); } diff --git a/engine/time/src/test/java/io/deephaven/time/TestDateTimeUtils.java b/engine/time/src/test/java/io/deephaven/time/TestDateTimeUtils.java index bbb61f2f505..76b9d1e201c 100644 --- a/engine/time/src/test/java/io/deephaven/time/TestDateTimeUtils.java +++ b/engine/time/src/test/java/io/deephaven/time/TestDateTimeUtils.java @@ -2012,7 +2012,7 @@ public void testPlusLocalDate() { // ok } } - + public void testPlusDuration() { final Duration d1 = Duration.ofSeconds(1); final Duration d2 = Duration.ofSeconds(2); @@ -2439,7 +2439,7 @@ public void testMultiply() { TestCase.assertNull(DateTimeUtils.multiply((Period) null, 3L)); TestCase.assertNull(DateTimeUtils.multiply(p, NULL_LONG)); - try{ + try { DateTimeUtils.multiply(p, Long.MAX_VALUE); TestCase.fail("This should have overflowed"); } catch (DateTimeUtils.DateTimeOverflowException e) { @@ -2462,21 +2462,21 @@ public void testMultiply() { TestCase.assertNull(DateTimeUtils.multiply((Duration) null, 3.0)); TestCase.assertNull(DateTimeUtils.multiply(d, NULL_DOUBLE)); - try{ + try { DateTimeUtils.multiply(d, Double.NaN); TestCase.fail("This should have excepted"); } catch (DateTimeUtils.DateTimeOverflowException e) { // ok } - try{ + try { DateTimeUtils.multiply(d, Double.POSITIVE_INFINITY); TestCase.fail("This should have excepted"); } catch (DateTimeUtils.DateTimeOverflowException e) { // ok } - try{ + try { DateTimeUtils.multiply(d, Double.NEGATIVE_INFINITY); TestCase.fail("This should have excepted"); } catch (DateTimeUtils.DateTimeOverflowException e) { @@ -2494,7 +2494,7 @@ public void testDivideDuration() { TestCase.assertNull(DateTimeUtils.divide((Duration) null, 3)); TestCase.assertNull(DateTimeUtils.divide(d, NULL_LONG)); - try{ + try { DateTimeUtils.divide(d, 0); TestCase.fail("This should have excepted"); } catch (DateTimeUtils.DateTimeOverflowException e) { @@ -2507,14 +2507,14 @@ public void testDivideDuration() { TestCase.assertNull(DateTimeUtils.divide((Duration) null, 3.0)); TestCase.assertNull(DateTimeUtils.divide(d, NULL_DOUBLE)); - try{ + try { DateTimeUtils.divide(d, 0.0); TestCase.fail("This should have excepted"); } catch (DateTimeUtils.DateTimeOverflowException e) { // ok } - try{ + try { DateTimeUtils.divide(d, Double.NaN); TestCase.fail("This should have excepted"); } catch (DateTimeUtils.DateTimeOverflowException e) { From 066a7245e2c4dbbaa48a0c4ff21093da05cde0df Mon Sep 17 00:00:00 2001 From: Chip Kent Date: Fri, 24 May 2024 12:39:19 -0600 Subject: [PATCH 04/11] Addressing code review. --- .../time/src/main/java/io/deephaven/time/DateTimeUtils.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java b/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java index 94f56bca616..51ccb332290 100644 --- a/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java +++ b/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java @@ -1958,7 +1958,11 @@ public static Duration multiply(final Duration duration, final long scalar) { return null; } - return duration.multipliedBy(scalar); + try { + return duration.multipliedBy(scalar); + } catch (ArithmeticException ex) { + throw new DateTimeOverflowException(ex); + } } /** From 8a29e47b6060a1cbdf0dba182927ad906072120f Mon Sep 17 00:00:00 2001 From: Chip Kent Date: Fri, 24 May 2024 12:40:19 -0600 Subject: [PATCH 05/11] Addressing code review. --- .../time/src/main/java/io/deephaven/time/DateTimeUtils.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java b/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java index 51ccb332290..a36ea6d43c2 100644 --- a/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java +++ b/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java @@ -2024,7 +2024,11 @@ public static Period multiply(final Period period, final int scalar) { return null; } - return period.multipliedBy(scalar); + try { + return period.multipliedBy(scalar); + } catch (ArithmeticException ex) { + throw new DateTimeOverflowException(ex); + } } /** From e5fddc5b27804a48b0ac608e29e60ec0b075ce5d Mon Sep 17 00:00:00 2001 From: Chip Kent Date: Fri, 24 May 2024 12:49:58 -0600 Subject: [PATCH 06/11] Addressing code review. --- .../main/java/io/deephaven/time/DateTimeUtils.java | 12 +++++++++--- .../java/io/deephaven/time/TestDateTimeUtils.java | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java b/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java index a36ea6d43c2..e171df3a0d2 100644 --- a/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java +++ b/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java @@ -1978,10 +1978,13 @@ public static Duration multiply(final long scalar, final Duration duration) { /** * Multiply a duration by a scalar. + *

+ * Because the scalar is a double, the result may not be exact. In particular, the result will be rounded to the + * nearest nanosecond. In the case of a tie, the result will be rounded up. * * @param duration the duration to multiply * @param scalar the scalar to multiply by - * @return {@code null} if either input is {@code null}; otherwise the duration multiplied by the scalar + * @return {@code null} if either input is {@code null}; otherwise the duration multiplied by the scalar. */ public static Duration multiply(final Duration duration, final double scalar) { if (duration == null || scalar == NULL_DOUBLE) { @@ -1998,7 +2001,7 @@ public static Duration multiply(final Duration duration, final double scalar) { throw new DateTimeOverflowException("Product value is too large to be cast to a long"); } - return Duration.ofNanos((long) product); + return Duration.ofNanos(Math.round(product)); } /** @@ -2093,6 +2096,9 @@ public static Duration divide(final Duration duration, final long scalar) { /** * Divide a duration by a scalar. + *

+ * Because the scalar is a double, the result may not be exact. In particular, the result will be rounded to the + * nearest nanosecond. In the case of a tie, the result will be rounded up. * * @param duration the duration to divide * @param scalar the scalar to divide by @@ -2111,7 +2117,7 @@ public static Duration divide(final Duration duration, final double scalar) { throw new DateTimeOverflowException("Scalar value is zero"); } - return Duration.ofNanos((long) (duration.toNanos() / scalar)); + return Duration.ofNanos(Math.round(duration.toNanos() / scalar)); } /** diff --git a/engine/time/src/test/java/io/deephaven/time/TestDateTimeUtils.java b/engine/time/src/test/java/io/deephaven/time/TestDateTimeUtils.java index 76b9d1e201c..2c394a62e35 100644 --- a/engine/time/src/test/java/io/deephaven/time/TestDateTimeUtils.java +++ b/engine/time/src/test/java/io/deephaven/time/TestDateTimeUtils.java @@ -2501,7 +2501,7 @@ public void testDivideDuration() { // ok } - TestCase.assertEquals(Duration.ofNanos(61728394L), DateTimeUtils.divide(d, 2.0)); + TestCase.assertEquals(Duration.ofNanos(61728395L), DateTimeUtils.divide(d, 2.0)); TestCase.assertEquals(Duration.ofNanos(0L), DateTimeUtils.divide(d, POS_INFINITY_DOUBLE)); TestCase.assertEquals(Duration.ofNanos(0L), DateTimeUtils.divide(d, NEG_INFINITY_DOUBLE)); TestCase.assertNull(DateTimeUtils.divide((Duration) null, 3.0)); From c0a0dc44e790af4751226d2871a069a100718034 Mon Sep 17 00:00:00 2001 From: Chip Kent Date: Fri, 24 May 2024 12:52:53 -0600 Subject: [PATCH 07/11] Addressing code review. --- .../src/main/java/io/deephaven/time/DateTimeUtils.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java b/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java index e171df3a0d2..6e284617d47 100644 --- a/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java +++ b/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java @@ -2087,11 +2087,11 @@ public static Duration divide(final Duration duration, final long scalar) { return null; } - if (scalar == 0) { - throw new DateTimeOverflowException("Scalar value is zero"); + try { + return duration.dividedBy(scalar); + } catch (ArithmeticException ex) { + throw new DateTimeOverflowException(ex); } - - return duration.dividedBy(scalar); } /** From 5a11c27a9b70bdf88610db4809c8748f4e87a8cc Mon Sep 17 00:00:00 2001 From: Chip Kent Date: Fri, 24 May 2024 14:04:32 -0600 Subject: [PATCH 08/11] Addressing code review. Removed floating point methods. --- .../java/io/deephaven/time/DateTimeUtils.java | 65 ------------------- .../io/deephaven/time/TestDateTimeUtils.java | 47 -------------- 2 files changed, 112 deletions(-) diff --git a/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java b/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java index 6e284617d47..606c37e12b4 100644 --- a/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java +++ b/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java @@ -1976,45 +1976,6 @@ public static Duration multiply(final long scalar, final Duration duration) { return multiply(duration, scalar); } - /** - * Multiply a duration by a scalar. - *

- * Because the scalar is a double, the result may not be exact. In particular, the result will be rounded to the - * nearest nanosecond. In the case of a tie, the result will be rounded up. - * - * @param duration the duration to multiply - * @param scalar the scalar to multiply by - * @return {@code null} if either input is {@code null}; otherwise the duration multiplied by the scalar. - */ - public static Duration multiply(final Duration duration, final double scalar) { - if (duration == null || scalar == NULL_DOUBLE) { - return null; - } - - if (Double.isNaN(scalar)) { - throw new DateTimeOverflowException("Scalar value is NaN"); - } - - final double product = duration.toNanos() * scalar; - - if (product > Long.MAX_VALUE || product < Long.MIN_VALUE) { - throw new DateTimeOverflowException("Product value is too large to be cast to a long"); - } - - return Duration.ofNanos(Math.round(product)); - } - - /** - * Multiply a duration by a scalar. - * - * @param duration the duration to multiply - * @param scalar the scalar to multiply by - * @return {@code null} if either input is {@code null}; otherwise the duration multiplied by the scalar - */ - public static Duration multiply(final double scalar, final Duration duration) { - return multiply(duration, scalar); - } - /** * Multiply a period by a scalar. * @@ -2094,32 +2055,6 @@ public static Duration divide(final Duration duration, final long scalar) { } } - /** - * Divide a duration by a scalar. - *

- * Because the scalar is a double, the result may not be exact. In particular, the result will be rounded to the - * nearest nanosecond. In the case of a tie, the result will be rounded up. - * - * @param duration the duration to divide - * @param scalar the scalar to divide by - * @return {@code null} if either input is {@code null}; otherwise the duration divide by the scalar - */ - public static Duration divide(final Duration duration, final double scalar) { - if (duration == null || scalar == NULL_DOUBLE) { - return null; - } - - if (Double.isNaN(scalar)) { - throw new DateTimeOverflowException("Scalar value is NaN"); - } - - if (scalar == 0) { - throw new DateTimeOverflowException("Scalar value is zero"); - } - - return Duration.ofNanos(Math.round(duration.toNanos() / scalar)); - } - /** * Returns the difference in nanoseconds between two instant values. * diff --git a/engine/time/src/test/java/io/deephaven/time/TestDateTimeUtils.java b/engine/time/src/test/java/io/deephaven/time/TestDateTimeUtils.java index 2c394a62e35..e578230bf2b 100644 --- a/engine/time/src/test/java/io/deephaven/time/TestDateTimeUtils.java +++ b/engine/time/src/test/java/io/deephaven/time/TestDateTimeUtils.java @@ -2456,32 +2456,6 @@ public void testMultiply() { TestCase.assertEquals(Duration.ofNanos(-370370367L), DateTimeUtils.multiply(d, -3)); TestCase.assertNull(DateTimeUtils.multiply((Duration) null, 3)); TestCase.assertNull(DateTimeUtils.multiply(d, NULL_LONG)); - - TestCase.assertEquals(Duration.ofNanos(246913578L), DateTimeUtils.multiply(d, 2.0)); - TestCase.assertEquals(Duration.ofNanos(246913578L), DateTimeUtils.multiply(2.0, d)); - TestCase.assertNull(DateTimeUtils.multiply((Duration) null, 3.0)); - TestCase.assertNull(DateTimeUtils.multiply(d, NULL_DOUBLE)); - - try { - DateTimeUtils.multiply(d, Double.NaN); - TestCase.fail("This should have excepted"); - } catch (DateTimeUtils.DateTimeOverflowException e) { - // ok - } - - try { - DateTimeUtils.multiply(d, Double.POSITIVE_INFINITY); - TestCase.fail("This should have excepted"); - } catch (DateTimeUtils.DateTimeOverflowException e) { - // ok - } - - try { - DateTimeUtils.multiply(d, Double.NEGATIVE_INFINITY); - TestCase.fail("This should have excepted"); - } catch (DateTimeUtils.DateTimeOverflowException e) { - // ok - } } public void testDivideDuration() { @@ -2500,27 +2474,6 @@ public void testDivideDuration() { } catch (DateTimeUtils.DateTimeOverflowException e) { // ok } - - TestCase.assertEquals(Duration.ofNanos(61728395L), DateTimeUtils.divide(d, 2.0)); - TestCase.assertEquals(Duration.ofNanos(0L), DateTimeUtils.divide(d, POS_INFINITY_DOUBLE)); - TestCase.assertEquals(Duration.ofNanos(0L), DateTimeUtils.divide(d, NEG_INFINITY_DOUBLE)); - TestCase.assertNull(DateTimeUtils.divide((Duration) null, 3.0)); - TestCase.assertNull(DateTimeUtils.divide(d, NULL_DOUBLE)); - - try { - DateTimeUtils.divide(d, 0.0); - TestCase.fail("This should have excepted"); - } catch (DateTimeUtils.DateTimeOverflowException e) { - // ok - } - - try { - DateTimeUtils.divide(d, Double.NaN); - TestCase.fail("This should have excepted"); - } catch (DateTimeUtils.DateTimeOverflowException e) { - // ok - } - } public void testDiffNanos() { From b489cf4b8b23f51ad33ae3ecf87eb68dcddd4eba Mon Sep 17 00:00:00 2001 From: Chip Kent Date: Tue, 4 Jun 2024 12:44:13 -0600 Subject: [PATCH 09/11] Addressing code review. More explicit overflow exception handling. --- .../java/io/deephaven/time/DateTimeUtils.java | 95 +++++++++++-------- 1 file changed, 55 insertions(+), 40 deletions(-) diff --git a/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java b/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java index 606c37e12b4..241910c4cff 100644 --- a/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java +++ b/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java @@ -1475,7 +1475,7 @@ public static ZonedDateTime excelToZonedDateTime(final double excel, @Nullable f * @param days number of days to add * @return {@code null} if either input is {@code null} or {@link QueryConstants#NULL_LONG}; otherwise the starting * date plus the specified number of days - * @throws DateTimeOverflowException if the resultant date time exceeds the supported range + * @throws DateTimeOverflowException if the datetime arithmetic overflows or underflows */ @ScriptApi @Nullable @@ -1486,7 +1486,7 @@ public static LocalDate plusDays(@Nullable final LocalDate date, final long days try { return date.plusDays(days); - } catch (Exception ex) { + } catch (DateTimeException | ArithmeticException ex) { throw new DateTimeOverflowException(ex); } } @@ -1497,7 +1497,7 @@ public static LocalDate plusDays(@Nullable final LocalDate date, final long days * @param date starting date * @param period time period * @return {@code null} if either input is {@code null}; otherwise the starting date plus the specified time period - * @throws DateTimeOverflowException if the resultant date time exceeds the supported range + * @throws DateTimeOverflowException if the datetime arithmetic overflows or underflows */ @ScriptApi @Nullable @@ -1508,7 +1508,7 @@ public static LocalDate plus(@Nullable final LocalDate date, final Period period try { return date.plus(period); - } catch (Exception ex) { + } catch (DateTimeException | ArithmeticException ex) { throw new DateTimeOverflowException(ex); } } @@ -1520,7 +1520,7 @@ public static LocalDate plus(@Nullable final LocalDate date, final Period period * @param nanos number of nanoseconds to add * @return {@code null} if either input is {@code null} or {@link QueryConstants#NULL_LONG}; otherwise the starting * instant plus the specified number of nanoseconds - * @throws DateTimeOverflowException if the resultant instant exceeds the supported range + * @throws DateTimeOverflowException if the datetime arithmetic overflows or underflows */ @ScriptApi @Nullable @@ -1531,7 +1531,7 @@ public static Instant plus(@Nullable final Instant instant, final long nanos) { try { return instant.plusNanos(nanos); - } catch (Exception ex) { + } catch (DateTimeException | ArithmeticException ex) { throw new DateTimeOverflowException(ex); } } @@ -1543,7 +1543,7 @@ public static Instant plus(@Nullable final Instant instant, final long nanos) { * @param nanos number of nanoseconds to add * @return {@code null} if either input is {@code null} or {@link QueryConstants#NULL_LONG}; otherwise the starting * zoned date time plus the specified number of nanoseconds - * @throws DateTimeOverflowException if the resultant zoned date time exceeds the supported range + * @throws DateTimeOverflowException if the datetime arithmetic overflows or underflows */ @ScriptApi @Nullable @@ -1554,7 +1554,7 @@ public static ZonedDateTime plus(@Nullable final ZonedDateTime dateTime, final l try { return dateTime.plusNanos(nanos); - } catch (Exception ex) { + } catch (DateTimeException | ArithmeticException ex) { throw new DateTimeOverflowException(ex); } } @@ -1566,7 +1566,7 @@ public static ZonedDateTime plus(@Nullable final ZonedDateTime dateTime, final l * @param duration time period * @return {@code null} if either input is {@code null} or {@link QueryConstants#NULL_LONG}; otherwise the starting * instant plus the specified time period - * @throws DateTimeOverflowException if the resultant instant exceeds the supported range + * @throws DateTimeOverflowException if the datetime arithmetic overflows or underflows */ @ScriptApi @Nullable @@ -1577,7 +1577,7 @@ public static Instant plus(@Nullable final Instant instant, @Nullable final Dura try { return instant.plus(duration); - } catch (Exception ex) { + } catch (DateTimeException | ArithmeticException ex) { throw new DateTimeOverflowException(ex); } } @@ -1589,7 +1589,7 @@ public static Instant plus(@Nullable final Instant instant, @Nullable final Dura * @param period time period * @return {@code null} if either input is {@code null} or {@link QueryConstants#NULL_LONG}; otherwise the starting * instant plus the specified time period - * @throws DateTimeOverflowException if the resultant instant exceeds the supported range + * @throws DateTimeOverflowException if the datetime arithmetic overflows or underflows */ @ScriptApi @Nullable @@ -1600,7 +1600,7 @@ public static Instant plus(@Nullable final Instant instant, @Nullable final Peri try { return instant.plus(period); - } catch (Exception ex) { + } catch (DateTimeException | ArithmeticException ex) { throw new DateTimeOverflowException(ex); } } @@ -1612,7 +1612,7 @@ public static Instant plus(@Nullable final Instant instant, @Nullable final Peri * @param duration time period * @return {@code null} if either input is {@code null} or {@link QueryConstants#NULL_LONG}; otherwise the starting * zoned date time plus the specified time period - * @throws DateTimeOverflowException if the resultant zoned date time exceeds the supported range + * @throws DateTimeOverflowException if the datetime arithmetic overflows or underflows */ @ScriptApi @Nullable @@ -1623,7 +1623,7 @@ public static ZonedDateTime plus(@Nullable final ZonedDateTime dateTime, @Nullab try { return dateTime.plus(duration); - } catch (Exception ex) { + } catch (DateTimeException | ArithmeticException ex) { throw new DateTimeOverflowException(ex); } } @@ -1635,7 +1635,7 @@ public static ZonedDateTime plus(@Nullable final ZonedDateTime dateTime, @Nullab * @param period time period * @return {@code null} if either input is {@code null} or {@link QueryConstants#NULL_LONG}; otherwise the starting * zoned date time plus the specified time period - * @throws DateTimeOverflowException if the resultant zoned date time exceeds the supported range + * @throws DateTimeOverflowException if the datetime arithmetic overflows or underflows */ @ScriptApi @Nullable @@ -1646,7 +1646,7 @@ public static ZonedDateTime plus(@Nullable final ZonedDateTime dateTime, @Nullab try { return dateTime.plus(period); - } catch (Exception ex) { + } catch (DateTimeException | ArithmeticException ex) { throw new DateTimeOverflowException(ex); } } @@ -1657,6 +1657,7 @@ public static ZonedDateTime plus(@Nullable final ZonedDateTime dateTime, @Nullab * @param duration1 first duration * @param duration2 second duration * @return {@code null} if either input is {@code null}; otherwise the sum of the two durations + * @throws DateTimeOverflowException if the datetime arithmetic overflows or underflows */ public static Duration plus(@Nullable final Duration duration1, @Nullable final Duration duration2) { if (duration1 == null || duration2 == null) { @@ -1665,7 +1666,7 @@ public static Duration plus(@Nullable final Duration duration1, @Nullable final try { return duration1.plus(duration2); - } catch (Exception ex) { + } catch (DateTimeException | ArithmeticException ex) { throw new DateTimeOverflowException(ex); } } @@ -1676,6 +1677,7 @@ public static Duration plus(@Nullable final Duration duration1, @Nullable final * @param period1 first period * @param period2 second period * @return {@code null} if either input is {@code null}; otherwise the sum of the two periods + * @throws DateTimeOverflowException if the datetime arithmetic overflows or underflows */ public static Period plus(@Nullable final Period period1, @Nullable final Period period2) { if (period1 == null || period2 == null) { @@ -1684,7 +1686,7 @@ public static Period plus(@Nullable final Period period1, @Nullable final Period try { return period1.plus(period2); - } catch (Exception ex) { + } catch (DateTimeException | ArithmeticException ex) { throw new DateTimeOverflowException(ex); } } @@ -1696,7 +1698,7 @@ public static Period plus(@Nullable final Period period1, @Nullable final Period * @param days number of days to subtract * @return {@code null} if either input is {@code null} or {@link QueryConstants#NULL_LONG}; otherwise the starting * date plus the specified number of days - * @throws DateTimeOverflowException if the resultant date time exceeds the supported range + * @throws DateTimeOverflowException if the datetime arithmetic overflows or underflows */ @ScriptApi @Nullable @@ -1707,7 +1709,7 @@ public static LocalDate minusDays(@Nullable final LocalDate date, final long day try { return date.minusDays(days); - } catch (Exception ex) { + } catch (DateTimeException | ArithmeticException ex) { throw new DateTimeOverflowException(ex); } } @@ -1718,7 +1720,7 @@ public static LocalDate minusDays(@Nullable final LocalDate date, final long day * @param date starting date * @param period time period * @return {@code null} if either input is {@code null}; otherwise the starting date minus the specified time period - * @throws DateTimeOverflowException if the resultant date time exceeds the supported range + * @throws DateTimeOverflowException if the datetime arithmetic overflows or underflows */ @ScriptApi @Nullable @@ -1729,7 +1731,7 @@ public static LocalDate minus(@Nullable final LocalDate date, final Period perio try { return date.minus(period); - } catch (Exception ex) { + } catch (DateTimeException | ArithmeticException ex) { throw new DateTimeOverflowException(ex); } } @@ -1741,7 +1743,7 @@ public static LocalDate minus(@Nullable final LocalDate date, final Period perio * @param nanos number of nanoseconds to subtract * @return {@code null} if either input is {@code null} or {@link QueryConstants#NULL_LONG}; otherwise the starting * instant minus the specified number of nanoseconds - * @throws DateTimeOverflowException if the resultant instant exceeds the supported range + * @throws DateTimeOverflowException if the datetime arithmetic overflows or underflows */ @ScriptApi @Nullable @@ -1752,7 +1754,7 @@ public static Instant minus(@Nullable final Instant instant, final long nanos) { try { return instant.minusNanos(nanos); - } catch (Exception ex) { + } catch (DateTimeException | ArithmeticException ex) { throw new DateTimeOverflowException(ex); } } @@ -1764,7 +1766,7 @@ public static Instant minus(@Nullable final Instant instant, final long nanos) { * @param nanos number of nanoseconds to subtract * @return {@code null} if either input is {@code null} or {@link QueryConstants#NULL_LONG}; otherwise the starting * zoned date time minus the specified number of nanoseconds - * @throws DateTimeOverflowException if the resultant zoned date time exceeds the supported range + * @throws DateTimeOverflowException if the datetime arithmetic overflows or underflows */ @ScriptApi @Nullable @@ -1775,7 +1777,7 @@ public static ZonedDateTime minus(@Nullable final ZonedDateTime dateTime, final try { return dateTime.minusNanos(nanos); - } catch (Exception ex) { + } catch (DateTimeException | ArithmeticException ex) { throw new DateTimeOverflowException(ex); } } @@ -1787,7 +1789,7 @@ public static ZonedDateTime minus(@Nullable final ZonedDateTime dateTime, final * @param duration time period * @return {@code null} if either input is {@code null} or {@link QueryConstants#NULL_LONG}; otherwise the starting * instant minus the specified time period - * @throws DateTimeOverflowException if the resultant instant exceeds the supported range + * @throws DateTimeOverflowException if the datetime arithmetic overflows or underflows */ @ScriptApi @Nullable @@ -1798,7 +1800,7 @@ public static Instant minus(@Nullable final Instant instant, @Nullable final Dur try { return instant.minus(duration); - } catch (Exception ex) { + } catch (DateTimeException | ArithmeticException ex) { throw new DateTimeOverflowException(ex); } } @@ -1810,7 +1812,7 @@ public static Instant minus(@Nullable final Instant instant, @Nullable final Dur * @param period time period * @return {@code null} if either input is {@code null} or {@link QueryConstants#NULL_LONG}; otherwise the starting * instant minus the specified time period - * @throws DateTimeOverflowException if the resultant instant exceeds the supported range + * @throws DateTimeOverflowException if the datetime arithmetic overflows or underflows */ @ScriptApi @Nullable @@ -1821,7 +1823,7 @@ public static Instant minus(@Nullable final Instant instant, @Nullable final Per try { return instant.minus(period); - } catch (Exception ex) { + } catch (DateTimeException | ArithmeticException ex) { throw new DateTimeOverflowException(ex); } } @@ -1833,7 +1835,7 @@ public static Instant minus(@Nullable final Instant instant, @Nullable final Per * @param duration time period * @return {@code null} if either input is {@code null} or {@link QueryConstants#NULL_LONG}; otherwise the starting * zoned date time minus the specified time period - * @throws DateTimeOverflowException if the resultant zoned date time exceeds the supported range + * @throws DateTimeOverflowException if the datetime arithmetic overflows or underflows */ @ScriptApi @Nullable @@ -1844,7 +1846,7 @@ public static ZonedDateTime minus(@Nullable final ZonedDateTime dateTime, @Nulla try { return dateTime.minus(duration); - } catch (Exception ex) { + } catch (DateTimeException | ArithmeticException ex) { throw new DateTimeOverflowException(ex); } } @@ -1856,7 +1858,7 @@ public static ZonedDateTime minus(@Nullable final ZonedDateTime dateTime, @Nulla * @param period time period * @return {@code null} if either input is {@code null} or {@link QueryConstants#NULL_LONG}; otherwise the starting * zoned date time minus the specified time period - * @throws DateTimeOverflowException if the resultant zoned date time exceeds the supported range + * @throws DateTimeOverflowException if the datetime arithmetic overflows or underflows */ @ScriptApi @Nullable @@ -1867,7 +1869,7 @@ public static ZonedDateTime minus(@Nullable final ZonedDateTime dateTime, @Nulla try { return dateTime.minus(period); - } catch (Exception ex) { + } catch (DateTimeException | ArithmeticException ex) { throw new DateTimeOverflowException(ex); } } @@ -1914,6 +1916,7 @@ public static long minus(@Nullable final ZonedDateTime dateTime1, @Nullable fina * @param duration1 first duration * @param duration2 second duration * @return {@code null} if either input is {@code null}; otherwise the difference of the two durations + * @throws DateTimeOverflowException if the datetime arithmetic overflows or underflows */ public static Duration minus(@Nullable final Duration duration1, @Nullable final Duration duration2) { if (duration1 == null || duration2 == null) { @@ -1922,7 +1925,7 @@ public static Duration minus(@Nullable final Duration duration1, @Nullable final try { return duration1.minus(duration2); - } catch (Exception ex) { + } catch (DateTimeException | ArithmeticException ex) { throw new DateTimeOverflowException(ex); } } @@ -1933,6 +1936,7 @@ public static Duration minus(@Nullable final Duration duration1, @Nullable final * @param period1 first period * @param period2 second period * @return {@code null} if either input is {@code null}; otherwise the difference of the two periods + * @throws DateTimeOverflowException if the datetime arithmetic overflows or underflows */ public static Period minus(@Nullable final Period period1, @Nullable final Period period2) { if (period1 == null || period2 == null) { @@ -1941,7 +1945,7 @@ public static Period minus(@Nullable final Period period1, @Nullable final Perio try { return period1.minus(period2); - } catch (Exception ex) { + } catch (DateTimeException | ArithmeticException ex) { throw new DateTimeOverflowException(ex); } } @@ -1952,6 +1956,7 @@ public static Period minus(@Nullable final Period period1, @Nullable final Perio * @param duration the duration to multiply * @param scalar the scalar to multiply by * @return {@code null} if either input is {@code null}; otherwise the duration multiplied by the scalar + * @throws DateTimeOverflowException if the datetime arithmetic overflows or underflows */ public static Duration multiply(final Duration duration, final long scalar) { if (duration == null || scalar == NULL_LONG) { @@ -1960,7 +1965,7 @@ public static Duration multiply(final Duration duration, final long scalar) { try { return duration.multipliedBy(scalar); - } catch (ArithmeticException ex) { + } catch (DateTimeException | ArithmeticException ex) { throw new DateTimeOverflowException(ex); } } @@ -1971,6 +1976,7 @@ public static Duration multiply(final Duration duration, final long scalar) { * @param duration the duration to multiply * @param scalar the scalar to multiply by * @return {@code null} if either input is {@code null}; otherwise the duration multiplied by the scalar + * @throws DateTimeOverflowException if the datetime arithmetic overflows or underflows */ public static Duration multiply(final long scalar, final Duration duration) { return multiply(duration, scalar); @@ -1982,6 +1988,7 @@ public static Duration multiply(final long scalar, final Duration duration) { * @param period the period to multiply * @param scalar the scalar to multiply by * @return {@code null} if either input is {@code null}; otherwise the period multiplied by the scalar + * @throws DateTimeOverflowException if the datetime arithmetic overflows or underflows */ public static Period multiply(final Period period, final int scalar) { if (period == null || scalar == NULL_INT) { @@ -1990,7 +1997,7 @@ public static Period multiply(final Period period, final int scalar) { try { return period.multipliedBy(scalar); - } catch (ArithmeticException ex) { + } catch (DateTimeException | ArithmeticException ex) { throw new DateTimeOverflowException(ex); } } @@ -2001,6 +2008,7 @@ public static Period multiply(final Period period, final int scalar) { * @param period the period to multiply * @param scalar the scalar to multiply by * @return {@code null} if either input is {@code null}; otherwise the period multiplied by the scalar + * @throws DateTimeOverflowException if the datetime arithmetic overflows or underflows */ public static Period multiply(final int scalar, final Period period) { return multiply(period, scalar); @@ -2012,6 +2020,7 @@ public static Period multiply(final int scalar, final Period period) { * @param period the period to multiply * @param scalar the scalar to multiply by * @return {@code null} if either input is {@code null}; otherwise the period multiplied by the scalar + * @throws DateTimeOverflowException if the datetime arithmetic overflows or underflows */ public static Period multiply(final Period period, final long scalar) { if (period == null || scalar == NULL_LONG) { @@ -2022,7 +2031,11 @@ public static Period multiply(final Period period, final long scalar) { throw new DateTimeOverflowException("Scalar value is too large to be cast to an int"); } - return period.multipliedBy((int) scalar); + try { + return period.multipliedBy((int) scalar); + } catch (DateTimeException | ArithmeticException ex) { + throw new DateTimeOverflowException(ex); + } } /** @@ -2031,6 +2044,7 @@ public static Period multiply(final Period period, final long scalar) { * @param period the period to multiply * @param scalar the scalar to multiply by * @return {@code null} if either input is {@code null}; otherwise the period multiplied by the scalar + * @throws DateTimeOverflowException if the datetime arithmetic overflows or underflows */ public static Period multiply(final long scalar, final Period period) { return multiply(period, scalar); @@ -2042,6 +2056,7 @@ public static Period multiply(final long scalar, final Period period) { * @param duration the duration to divide * @param scalar the scalar to divide by * @return {@code null} if either input is {@code null}; otherwise the duration divide by the scalar + * @throws DateTimeOverflowException if the datetime arithmetic overflows or underflows */ public static Duration divide(final Duration duration, final long scalar) { if (duration == null || scalar == NULL_LONG) { @@ -2050,7 +2065,7 @@ public static Duration divide(final Duration duration, final long scalar) { try { return duration.dividedBy(scalar); - } catch (ArithmeticException ex) { + } catch (DateTimeException | ArithmeticException ex) { throw new DateTimeOverflowException(ex); } } From f9d369d626240a2f9d02db6b48400508e1b076bf Mon Sep 17 00:00:00 2001 From: Chip Kent Date: Tue, 18 Jun 2024 09:14:02 -0600 Subject: [PATCH 10/11] Removed multiply operations with period and long. These will be in a separate PR. --- .../java/io/deephaven/time/DateTimeUtils.java | 36 ------------------- .../io/deephaven/time/TestDateTimeUtils.java | 17 --------- 2 files changed, 53 deletions(-) diff --git a/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java b/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java index 241910c4cff..6883db68f8b 100644 --- a/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java +++ b/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java @@ -2014,42 +2014,6 @@ public static Period multiply(final int scalar, final Period period) { return multiply(period, scalar); } - /** - * Multiply a period by a scalar. - * - * @param period the period to multiply - * @param scalar the scalar to multiply by - * @return {@code null} if either input is {@code null}; otherwise the period multiplied by the scalar - * @throws DateTimeOverflowException if the datetime arithmetic overflows or underflows - */ - public static Period multiply(final Period period, final long scalar) { - if (period == null || scalar == NULL_LONG) { - return null; - } - - if (scalar > Integer.MAX_VALUE || scalar < Integer.MIN_VALUE) { - throw new DateTimeOverflowException("Scalar value is too large to be cast to an int"); - } - - try { - return period.multipliedBy((int) scalar); - } catch (DateTimeException | ArithmeticException ex) { - throw new DateTimeOverflowException(ex); - } - } - - /** - * Multiply a period by a scalar. - * - * @param period the period to multiply - * @param scalar the scalar to multiply by - * @return {@code null} if either input is {@code null}; otherwise the period multiplied by the scalar - * @throws DateTimeOverflowException if the datetime arithmetic overflows or underflows - */ - public static Period multiply(final long scalar, final Period period) { - return multiply(period, scalar); - } - /** * Divide a duration by a scalar. * diff --git a/engine/time/src/test/java/io/deephaven/time/TestDateTimeUtils.java b/engine/time/src/test/java/io/deephaven/time/TestDateTimeUtils.java index e578230bf2b..5473c8ec029 100644 --- a/engine/time/src/test/java/io/deephaven/time/TestDateTimeUtils.java +++ b/engine/time/src/test/java/io/deephaven/time/TestDateTimeUtils.java @@ -2428,23 +2428,6 @@ public void testMultiply() { TestCase.assertNull(DateTimeUtils.multiply((Period) null, 3)); TestCase.assertNull(DateTimeUtils.multiply(p, NULL_INT)); - TestCase.assertEquals(Period.ofDays(6), DateTimeUtils.multiply(p, 2L)); - TestCase.assertEquals(Period.ofDays(6), DateTimeUtils.multiply(2L, p)); - TestCase.assertEquals(Period.ofDays(9), DateTimeUtils.multiply(p, 3L)); - TestCase.assertEquals(Period.ofDays(3), DateTimeUtils.multiply(p, 1L)); - TestCase.assertEquals(Period.ofDays(0), DateTimeUtils.multiply(p, 0L)); - TestCase.assertEquals(Period.ofDays(-3), DateTimeUtils.multiply(p, -1L)); - TestCase.assertEquals(Period.ofDays(-6), DateTimeUtils.multiply(p, -2L)); - TestCase.assertEquals(Period.ofDays(-9), DateTimeUtils.multiply(p, -3L)); - TestCase.assertNull(DateTimeUtils.multiply((Period) null, 3L)); - TestCase.assertNull(DateTimeUtils.multiply(p, NULL_LONG)); - - try { - DateTimeUtils.multiply(p, Long.MAX_VALUE); - TestCase.fail("This should have overflowed"); - } catch (DateTimeUtils.DateTimeOverflowException e) { - // ok - } TestCase.assertEquals(Duration.ofNanos(246913578L), DateTimeUtils.multiply(d, 2)); TestCase.assertEquals(Duration.ofNanos(246913578L), DateTimeUtils.multiply(2, d)); From d805d5e632efc8cbaaeba925b12f42dc1a38dccf Mon Sep 17 00:00:00 2001 From: Chip Kent Date: Tue, 18 Jun 2024 10:16:33 -0600 Subject: [PATCH 11/11] Spotless --- .../time/src/main/java/io/deephaven/time/DateTimeUtils.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java b/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java index f249c1a3eae..ce572dd30fc 100644 --- a/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java +++ b/engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java @@ -1680,7 +1680,8 @@ public static LocalDateTime plus(@Nullable final LocalDateTime localDateTime, fi * * @param localDate starting local date * @param period time period - * @return {@code null} if either input is {@code null}; otherwise the starting local date plus the specified time period + * @return {@code null} if either input is {@code null}; otherwise the starting local date plus the specified time + * period * @throws DateTimeOverflowException if the datetime arithmetic overflows or underflows */ @ScriptApi @@ -1949,7 +1950,8 @@ public static LocalDateTime minus(@Nullable final LocalDateTime localDateTime, f * * @param localDate starting local date * @param period time period - * @return {@code null} if either input is {@code null}; otherwise the starting local date minus the specified time period + * @return {@code null} if either input is {@code null}; otherwise the starting local date minus the specified time + * period * @throws DateTimeOverflowException if the datetime arithmetic overflows or underflows */ @ScriptApi