From 02d8bd26ef5a8a6f840d4cc98f669ea81c534487 Mon Sep 17 00:00:00 2001 From: Laurent Goujon Date: Mon, 6 Nov 2023 11:34:40 -0800 Subject: [PATCH] GH-38578: [Java][FlightSQL] Remove joda usage from flight-sql library (#38579) ### Rationale for this change [joda](https://www.joda.org/joda-time/) is a very popular date/time manipulation library for java but the introduction of `java.time` package makes it obsolete and author actually recommends using `java.time` over `joda` > Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project. ### What changes are included in this PR? Change include the use of `java.time` classes over `joda` classes and the removal of `joda` library as a dependency ### Are these changes tested? As there is no behavior change, it is covered by the existing tests * Closes: #38578 Authored-by: Laurent Goujon Signed-off-by: David Li --- java/flight/flight-sql-jdbc-core/pom.xml | 6 -- ...ArrowFlightJdbcIntervalVectorAccessor.java | 7 +- .../jdbc/utils/IntervalStringUtils.java | 15 ++-- ...wFlightJdbcIntervalVectorAccessorTest.java | 74 ++++++++++--------- 4 files changed, 49 insertions(+), 53 deletions(-) diff --git a/java/flight/flight-sql-jdbc-core/pom.xml b/java/flight/flight-sql-jdbc-core/pom.xml index 8a0e62bde8471..cbeaa88f1e2f7 100644 --- a/java/flight/flight-sql-jdbc-core/pom.xml +++ b/java/flight/flight-sql-jdbc-core/pom.xml @@ -136,12 +136,6 @@ bcpkix-jdk15on 1.61 - - - joda-time - joda-time - 2.10.14 - diff --git a/java/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/accessor/impl/calendar/ArrowFlightJdbcIntervalVectorAccessor.java b/java/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/accessor/impl/calendar/ArrowFlightJdbcIntervalVectorAccessor.java index 283dc9160a9e9..21d1c15712cdb 100644 --- a/java/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/accessor/impl/calendar/ArrowFlightJdbcIntervalVectorAccessor.java +++ b/java/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/accessor/impl/calendar/ArrowFlightJdbcIntervalVectorAccessor.java @@ -22,6 +22,8 @@ import static org.apache.arrow.vector.util.DateUtility.yearsToMonths; import java.sql.SQLException; +import java.time.Duration; +import java.time.Period; import java.util.function.IntSupplier; import org.apache.arrow.driver.jdbc.accessor.ArrowFlightJdbcAccessor; @@ -31,7 +33,6 @@ import org.apache.arrow.vector.IntervalYearVector; import org.apache.arrow.vector.holders.NullableIntervalDayHolder; import org.apache.arrow.vector.holders.NullableIntervalYearHolder; -import org.joda.time.Period; /** * Accessor for the Arrow type {@link IntervalDayVector}. @@ -62,7 +63,7 @@ public ArrowFlightJdbcIntervalVectorAccessor(IntervalDayVector vector, } else { final int days = holder.days; final int millis = holder.milliseconds; - return formatIntervalDay(new Period().plusDays(days).plusMillis(millis)); + return formatIntervalDay(Duration.ofDays(days).plusMillis(millis)); } }; objectClass = java.time.Duration.class; @@ -89,7 +90,7 @@ public ArrowFlightJdbcIntervalVectorAccessor(IntervalYearVector vector, final int interval = holder.value; final int years = (interval / yearsToMonths); final int months = (interval % yearsToMonths); - return formatIntervalYear(new Period().plusYears(years).plusMonths(months)); + return formatIntervalYear(Period.ofYears(years).plusMonths(months)); } }; objectClass = java.time.Period.class; diff --git a/java/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/IntervalStringUtils.java b/java/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/IntervalStringUtils.java index 05643274ac348..fdf6c508d93b0 100644 --- a/java/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/IntervalStringUtils.java +++ b/java/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/IntervalStringUtils.java @@ -17,8 +17,10 @@ package org.apache.arrow.driver.jdbc.utils; +import java.time.Duration; +import java.time.Period; + import org.apache.arrow.vector.util.DateUtility; -import org.joda.time.Period; /** * Utility class to format periods similar to Oracle's representation @@ -36,7 +38,7 @@ private IntervalStringUtils( ) {} * For example, the string "+21-02" defines an interval of 21 years and 2 months. */ public static String formatIntervalYear(final Period p) { - long months = p.getYears() * (long) DateUtility.yearsToMonths + p.getMonths(); + long months = p.toTotalMonths(); boolean neg = false; if (months < 0) { months = -months; @@ -53,8 +55,8 @@ public static String formatIntervalYear(final Period p) { * For example, the string "-001 18:25:16.766" defines an interval of * - 1 day 18 hours 25 minutes 16 seconds and 766 milliseconds. */ - public static String formatIntervalDay(final Period p) { - long millis = p.getDays() * (long) DateUtility.daysToStandardMillis + millisFromPeriod(p); + public static String formatIntervalDay(final Duration d) { + long millis = d.toMillis(); boolean neg = false; if (millis < 0) { @@ -76,9 +78,4 @@ public static String formatIntervalDay(final Period p) { return String.format("%c%03d %02d:%02d:%02d.%03d", neg ? '-' : '+', days, hours, minutes, seconds, millis); } - - public static int millisFromPeriod(Period period) { - return period.getHours() * DateUtility.hoursToMillis + period.getMinutes() * DateUtility.minutesToMillis + - period.getSeconds() * DateUtility.secondsToMillis + period.getMillis(); - } } diff --git a/java/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/accessor/impl/calendar/ArrowFlightJdbcIntervalVectorAccessorTest.java b/java/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/accessor/impl/calendar/ArrowFlightJdbcIntervalVectorAccessorTest.java index ea228692202a7..322b7d40bd6e1 100644 --- a/java/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/accessor/impl/calendar/ArrowFlightJdbcIntervalVectorAccessorTest.java +++ b/java/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/accessor/impl/calendar/ArrowFlightJdbcIntervalVectorAccessorTest.java @@ -21,7 +21,6 @@ import static org.apache.arrow.driver.jdbc.utils.IntervalStringUtils.formatIntervalYear; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; -import static org.joda.time.Period.parse; import java.time.Duration; import java.time.Period; @@ -142,57 +141,62 @@ private String getStringOnVector(ValueVector vector, int index) { if (object == null) { return null; } else if (vector instanceof IntervalDayVector) { - return formatIntervalDay(parse(object)); + return formatIntervalDay(Duration.parse(object)); } else if (vector instanceof IntervalYearVector) { - return formatIntervalYear(parse(object)); + return formatIntervalYear(Period.parse(object)); } return null; } @Test public void testShouldGetIntervalYear( ) { - Assert.assertEquals("-002-00", formatIntervalYear(parse("P-2Y"))); - Assert.assertEquals("-001-01", formatIntervalYear(parse("P-1Y-1M"))); - Assert.assertEquals("-001-02", formatIntervalYear(parse("P-1Y-2M"))); - Assert.assertEquals("-002-03", formatIntervalYear(parse("P-2Y-3M"))); - Assert.assertEquals("-002-04", formatIntervalYear(parse("P-2Y-4M"))); - Assert.assertEquals("-011-01", formatIntervalYear(parse("P-11Y-1M"))); - Assert.assertEquals("+002-00", formatIntervalYear(parse("P+2Y"))); - Assert.assertEquals("+001-01", formatIntervalYear(parse("P+1Y1M"))); - Assert.assertEquals("+001-02", formatIntervalYear(parse("P+1Y2M"))); - Assert.assertEquals("+002-03", formatIntervalYear(parse("P+2Y3M"))); - Assert.assertEquals("+002-04", formatIntervalYear(parse("P+2Y4M"))); - Assert.assertEquals("+011-01", formatIntervalYear(parse("P+11Y1M"))); + Assert.assertEquals("-002-00", formatIntervalYear(Period.parse("P-2Y"))); + Assert.assertEquals("-001-01", formatIntervalYear(Period.parse("P-1Y-1M"))); + Assert.assertEquals("-001-02", formatIntervalYear(Period.parse("P-1Y-2M"))); + Assert.assertEquals("-002-03", formatIntervalYear(Period.parse("P-2Y-3M"))); + Assert.assertEquals("-002-04", formatIntervalYear(Period.parse("P-2Y-4M"))); + Assert.assertEquals("-011-01", formatIntervalYear(Period.parse("P-11Y-1M"))); + Assert.assertEquals("+002-00", formatIntervalYear(Period.parse("P+2Y"))); + Assert.assertEquals("+001-01", formatIntervalYear(Period.parse("P+1Y1M"))); + Assert.assertEquals("+001-02", formatIntervalYear(Period.parse("P+1Y2M"))); + Assert.assertEquals("+002-03", formatIntervalYear(Period.parse("P+2Y3M"))); + Assert.assertEquals("+002-04", formatIntervalYear(Period.parse("P+2Y4M"))); + Assert.assertEquals("+011-01", formatIntervalYear(Period.parse("P+11Y1M"))); } @Test public void testShouldGetIntervalDay( ) { - Assert.assertEquals("-001 00:00:00.000", formatIntervalDay(parse("PT-24H"))); - Assert.assertEquals("+001 00:00:00.000", formatIntervalDay(parse("PT+24H"))); - Assert.assertEquals("-000 01:00:00.000", formatIntervalDay(parse("PT-1H"))); - Assert.assertEquals("-000 01:00:00.001", formatIntervalDay(parse("PT-1H-0M-00.001S"))); - Assert.assertEquals("-000 01:01:01.000", formatIntervalDay(parse("PT-1H-1M-1S"))); - Assert.assertEquals("-000 02:02:02.002", formatIntervalDay(parse("PT-2H-2M-02.002S"))); - Assert.assertEquals("-000 23:59:59.999", formatIntervalDay(parse("PT-23H-59M-59.999S"))); - Assert.assertEquals("-000 11:59:00.100", formatIntervalDay(parse("PT-11H-59M-00.100S"))); - Assert.assertEquals("-000 05:02:03.000", formatIntervalDay(parse("PT-5H-2M-3S"))); - Assert.assertEquals("-000 22:22:22.222", formatIntervalDay(parse("PT-22H-22M-22.222S"))); - Assert.assertEquals("+000 01:00:00.000", formatIntervalDay(parse("PT+1H"))); - Assert.assertEquals("+000 01:00:00.001", formatIntervalDay(parse("PT+1H0M00.001S"))); - Assert.assertEquals("+000 01:01:01.000", formatIntervalDay(parse("PT+1H1M1S"))); - Assert.assertEquals("+000 02:02:02.002", formatIntervalDay(parse("PT+2H2M02.002S"))); - Assert.assertEquals("+000 23:59:59.999", formatIntervalDay(parse("PT+23H59M59.999S"))); - Assert.assertEquals("+000 11:59:00.100", formatIntervalDay(parse("PT+11H59M00.100S"))); - Assert.assertEquals("+000 05:02:03.000", formatIntervalDay(parse("PT+5H2M3S"))); - Assert.assertEquals("+000 22:22:22.222", formatIntervalDay(parse("PT+22H22M22.222S"))); + Assert.assertEquals("-001 00:00:00.000", formatIntervalDay(Duration.parse("PT-24H"))); + Assert.assertEquals("+001 00:00:00.000", formatIntervalDay(Duration.parse("PT+24H"))); + Assert.assertEquals("-000 01:00:00.000", formatIntervalDay(Duration.parse("PT-1H"))); + // "JDK-8054978: java.time.Duration.parse() fails for negative duration with 0 seconds and nanos" not fixed on JDK8 + //Assert.assertEquals("-000 01:00:00.001", formatIntervalDay(Duration.parse("PT-1H-0M-00.001S"))); + Assert.assertEquals("-000 01:00:00.001", formatIntervalDay(Duration.ofHours(-1).minusMillis(1))); + Assert.assertEquals("-000 01:01:01.000", formatIntervalDay(Duration.parse("PT-1H-1M-1S"))); + Assert.assertEquals("-000 02:02:02.002", formatIntervalDay(Duration.parse("PT-2H-2M-02.002S"))); + Assert.assertEquals("-000 23:59:59.999", formatIntervalDay(Duration.parse("PT-23H-59M-59.999S"))); + // "JDK-8054978: java.time.Duration.parse() fails for negative duration with 0 seconds and nanos" not fixed on JDK8 + //Assert.assertEquals("-000 11:59:00.100", formatIntervalDay(Duration.parse("PT-11H-59M-00.100S"))); + Assert.assertEquals("-000 11:59:00.100", + formatIntervalDay(Duration.ofHours(-11).minusMinutes(59).minusMillis(100))); + Assert.assertEquals("-000 05:02:03.000", formatIntervalDay(Duration.parse("PT-5H-2M-3S"))); + Assert.assertEquals("-000 22:22:22.222", formatIntervalDay(Duration.parse("PT-22H-22M-22.222S"))); + Assert.assertEquals("+000 01:00:00.000", formatIntervalDay(Duration.parse("PT+1H"))); + Assert.assertEquals("+000 01:00:00.001", formatIntervalDay(Duration.parse("PT+1H0M00.001S"))); + Assert.assertEquals("+000 01:01:01.000", formatIntervalDay(Duration.parse("PT+1H1M1S"))); + Assert.assertEquals("+000 02:02:02.002", formatIntervalDay(Duration.parse("PT+2H2M02.002S"))); + Assert.assertEquals("+000 23:59:59.999", formatIntervalDay(Duration.parse("PT+23H59M59.999S"))); + Assert.assertEquals("+000 11:59:00.100", formatIntervalDay(Duration.parse("PT+11H59M00.100S"))); + Assert.assertEquals("+000 05:02:03.000", formatIntervalDay(Duration.parse("PT+5H2M3S"))); + Assert.assertEquals("+000 22:22:22.222", formatIntervalDay(Duration.parse("PT+22H22M22.222S"))); } @Test public void testIntervalDayWithJodaPeriodObject() { Assert.assertEquals("+1567 00:00:00.000", - formatIntervalDay(new org.joda.time.Period().plusDays(1567))); + formatIntervalDay(Duration.ofDays(1567))); Assert.assertEquals("-1567 00:00:00.000", - formatIntervalDay(new org.joda.time.Period().minusDays(1567))); + formatIntervalDay(Duration.ofDays(-1567))); } @Test