This is an automated email from the ASF dual-hosted git repository.
cutlerb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow.git
The following commit(s) were added to refs/heads/master by this push:
new fb8704d ARROW-2015: [Java] Replace Joda time with Java 8 time
fb8704d is described below
commit fb8704d73852b4487f5d7f748a9fce2d2c13d584
Author: Bryan Cutler <[email protected]>
AuthorDate: Fri Mar 8 14:30:38 2019 -0800
ARROW-2015: [Java] Replace Joda time with Java 8 time
This removes the use of the Joda time library in Arrow Java and replaces it
with Java 8 java.time, as recommended by JSR-310. Arrow APIs that previously
return a Joda time object will now return a java.time object. This includes the
`getObject` method of date, time, timestamp and interval vectors. Most classes
have an equivalent counterpart in java.time and usually required only a small
change to use the new API. Some of the notable changes:
* IntervalDayVector` previously used `Period` as a friendly-type, now uses
java.time.Duration to give intervals in days and time. `InvervalYearVector`
still uses `Period` for intervals in year, month, day.
* `LocalDateTime` is similar but the constructor `LocalDateTime.of` accepts
fraction of a second as nanoseconds, where with Joda time it could be in
milliseconds.
* `DateUtility` removed methods for Period conversions because they are
done better in java.time.Period now. Also added methods to convert internal
time vals to `LocalDateTime` in UTC that is used in vector and holder reader
classes.
Author: Bryan Cutler <[email protected]>
Closes #2966 from BryanCutler/remove-joda-time-ARROW-2015 and squashes the
following commits:
b5d3c0e <Bryan Cutler> fixed style checks
51468d7 <Bryan Cutler> Replace Joda time with Java 8 time
---
java/gandiva/pom.xml | 6 --
.../arrow/gandiva/evaluator/BaseEvaluatorTest.java | 4 +-
java/vector/pom.xml | 5 --
.../src/main/codegen/data/ValueVectorTypes.tdd | 2 +-
.../src/main/codegen/includes/vv_imports.ftl | 9 ++-
.../codegen/templates/AbstractFieldReader.java | 6 +-
.../main/codegen/templates/HolderReaderImpl.java | 19 ++++--
.../src/main/codegen/templates/NullReader.java | 6 +-
.../src/main/codegen/templates/UnionReader.java | 6 +-
.../org/apache/arrow/vector/DateMilliVector.java | 8 +--
.../org/apache/arrow/vector/IntervalDayVector.java | 8 +--
.../apache/arrow/vector/IntervalYearVector.java | 9 ++-
.../org/apache/arrow/vector/TimeMilliVector.java | 10 +--
.../apache/arrow/vector/TimeStampMicroVector.java | 11 ++--
.../apache/arrow/vector/TimeStampMilliVector.java | 8 +--
.../apache/arrow/vector/TimeStampNanoVector.java | 9 ++-
.../apache/arrow/vector/TimeStampSecVector.java | 8 +--
.../org/apache/arrow/vector/util/DateUtility.java | 77 +++++++++++++---------
.../main/java/org/joda/time/LocalDateTimes.java | 29 --------
.../java/org/apache/arrow/vector/TestCopyFrom.java | 23 ++++---
.../vector/complex/writer/TestComplexWriter.java | 10 +--
.../org/apache/arrow/vector/ipc/BaseFileTest.java | 48 ++++++++------
22 files changed, 153 insertions(+), 168 deletions(-)
diff --git a/java/gandiva/pom.xml b/java/gandiva/pom.xml
index 3469c9f..ded334c 100644
--- a/java/gandiva/pom.xml
+++ b/java/gandiva/pom.xml
@@ -62,12 +62,6 @@
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
- <dependency>
- <groupId>joda-time</groupId>
- <artifactId>joda-time</artifactId>
- <version>2.10</version>
- <scope>test</scope>
- </dependency>
</dependencies>
<profiles>
<profile>
diff --git
a/java/gandiva/src/test/java/org/apache/arrow/gandiva/evaluator/BaseEvaluatorTest.java
b/java/gandiva/src/test/java/org/apache/arrow/gandiva/evaluator/BaseEvaluatorTest.java
index 97c2883..2fd5a24 100644
---
a/java/gandiva/src/test/java/org/apache/arrow/gandiva/evaluator/BaseEvaluatorTest.java
+++
b/java/gandiva/src/test/java/org/apache/arrow/gandiva/evaluator/BaseEvaluatorTest.java
@@ -19,6 +19,7 @@ package org.apache.arrow.gandiva.evaluator;
import java.math.BigDecimal;
import java.math.BigInteger;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
@@ -37,7 +38,6 @@ import org.apache.arrow.vector.ipc.message.ArrowRecordBatch;
import org.apache.arrow.vector.types.FloatingPointPrecision;
import org.apache.arrow.vector.types.pojo.ArrowType;
import org.apache.arrow.vector.types.pojo.Schema;
-import org.joda.time.Instant;
import org.junit.After;
import org.junit.Before;
@@ -265,7 +265,7 @@ class BaseEvaluatorTest {
ArrowBuf buffer = allocator.buffer(dates.length * 8);
for (int i = 0; i < dates.length; i++) {
Instant instant = Instant.parse(dates[i]);
- buffer.writeLong(instant.getMillis());
+ buffer.writeLong(instant.toEpochMilli());
}
return buffer;
diff --git a/java/vector/pom.xml b/java/vector/pom.xml
index 3f32752..37b042e 100644
--- a/java/vector/pom.xml
+++ b/java/vector/pom.xml
@@ -32,11 +32,6 @@
<version>${project.version}</version>
</dependency>
<dependency>
- <groupId>joda-time</groupId>
- <artifactId>joda-time</artifactId>
- <version>2.9.9</version>
- </dependency>
- <dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
diff --git a/java/vector/src/main/codegen/data/ValueVectorTypes.tdd
b/java/vector/src/main/codegen/data/ValueVectorTypes.tdd
index 71eed91..329422f 100644
--- a/java/vector/src/main/codegen/data/ValueVectorTypes.tdd
+++ b/java/vector/src/main/codegen/data/ValueVectorTypes.tdd
@@ -106,7 +106,7 @@
javaType: "ArrowBuf",
boxedType: "ArrowBuf",
minor: [
- { class: "IntervalDay", millisecondsOffset: 4, friendlyType: "Period",
fields: [ {name: "days", type:"int"}, {name: "milliseconds", type:"int"}] }
+ { class: "IntervalDay", millisecondsOffset: 4, friendlyType:
"Duration", fields: [ {name: "days", type:"int"}, {name: "milliseconds",
type:"int"}] }
]
},
{
diff --git a/java/vector/src/main/codegen/includes/vv_imports.ftl
b/java/vector/src/main/codegen/includes/vv_imports.ftl
index 7bd884c..920c528 100644
--- a/java/vector/src/main/codegen/includes/vv_imports.ftl
+++ b/java/vector/src/main/codegen/includes/vv_imports.ftl
@@ -54,11 +54,10 @@ import java.sql.Time;
import java.sql.Timestamp;
import java.math.BigDecimal;
import java.math.BigInteger;
-
-import org.joda.time.DateTime;
-import org.joda.time.LocalDateTime;
-import org.joda.time.Period;
-
+import java.time.Duration;
+import java.time.LocalDateTime;
+import java.time.Period;
+import java.time.ZonedDateTime;
diff --git a/java/vector/src/main/codegen/templates/AbstractFieldReader.java
b/java/vector/src/main/codegen/templates/AbstractFieldReader.java
index d1d2bdf..05c1296 100644
--- a/java/vector/src/main/codegen/templates/AbstractFieldReader.java
+++ b/java/vector/src/main/codegen/templates/AbstractFieldReader.java
@@ -49,9 +49,9 @@ abstract class AbstractFieldReader extends AbstractBaseReader
implements FieldRe
return null;
}
- <#list ["Object", "BigDecimal", "Integer", "Long", "Boolean",
- "Character", "LocalDateTime", "Period", "Double", "Float",
- "Text", "String", "Byte", "Short", "byte[]"] as friendlyType>
+ <#list ["Object", "BigDecimal", "Short", "Integer", "Long", "Boolean",
+ "LocalDateTime", "Duration", "Period", "Double", "Float",
+ "Character", "Text", "String", "Byte", "byte[]"] as friendlyType>
<#assign safeType=friendlyType />
<#if safeType=="byte[]"><#assign safeType="ByteArray" /></#if>
public ${friendlyType} read${safeType}(int arrayIndex) {
diff --git a/java/vector/src/main/codegen/templates/HolderReaderImpl.java
b/java/vector/src/main/codegen/templates/HolderReaderImpl.java
index 264e8c1..629bb73 100644
--- a/java/vector/src/main/codegen/templates/HolderReaderImpl.java
+++ b/java/vector/src/main/codegen/templates/HolderReaderImpl.java
@@ -37,11 +37,6 @@ package org.apache.arrow.vector.complex.impl;
<#include "/@includes/vv_imports.ftl" />
-import java.math.BigDecimal;
-import java.math.BigInteger;
-
-import org.joda.time.Period;
-
// Source code generated using FreeMarker template ${.template_name}
@SuppressWarnings("unused")
@@ -118,8 +113,9 @@ public class ${holderMode}${name}HolderReaderImpl extends
AbstractFieldReader {
return text;
</#if>
<#elseif minor.class == "IntervalDay">
- Period p = new Period();
- return p.plusDays(holder.days).plusMillis(holder.milliseconds);
+ return Duration.ofDays(holder.days).plusMillis(holder.milliseconds);
+ <#elseif minor.class == "IntervalYear">
+ return Period.ofMonths(holder.value);
<#elseif minor.class == "Bit" >
return new Boolean(holder.value != 0);
<#elseif minor.class == "Decimal">
@@ -131,6 +127,15 @@ public class ${holderMode}${name}HolderReaderImpl extends
AbstractFieldReader {
byte[] value = new byte [holder.byteWidth];
holder.buffer.getBytes(0, value, 0, holder.byteWidth);
return value;
+ <#elseif minor.class == "TimeStampSec">
+ final long millis =
java.util.concurrent.TimeUnit.SECONDS.toMillis(holder.value);
+ return DateUtility.getLocalDateTimeFromEpochMilli(millis);
+ <#elseif minor.class == "TimeStampMilli" || minor.class == "DateMilli" ||
minor.class == "TimeMilli">
+ return DateUtility.getLocalDateTimeFromEpochMilli(holder.value);
+ <#elseif minor.class == "TimeStampMicro">
+ return DateUtility.getLocalDateTimeFromEpochMicro(holder.value);
+ <#elseif minor.class == "TimeStampNano">
+ return DateUtility.getLocalDateTimeFromEpochNano(holder.value);
<#else>
${friendlyType} value = new ${friendlyType}(this.holder.value);
return value;
diff --git a/java/vector/src/main/codegen/templates/NullReader.java
b/java/vector/src/main/codegen/templates/NullReader.java
index d4ed6e8..f5ef5ae 100644
--- a/java/vector/src/main/codegen/templates/NullReader.java
+++ b/java/vector/src/main/codegen/templates/NullReader.java
@@ -126,9 +126,9 @@ public class NullReader extends AbstractBaseReader
implements FieldReader{
throw new IllegalArgumentException(String.format("You tried to read a %s
type when you are using a ValueReader of type %s.", name,
this.getClass().getSimpleName()));
}
- <#list ["Object", "BigDecimal", "Integer", "Long", "Boolean",
- "Character", "LocalDateTime", "Period", "Double", "Float",
- "Text", "String", "Byte", "Short", "byte[]"] as friendlyType>
+ <#list ["Object", "BigDecimal", "Short", "Integer", "Long", "Boolean",
+ "LocalDateTime", "Duration", "Period", "Double", "Float",
+ "Character", "Text", "String", "Byte", "byte[]"] as friendlyType>
<#assign safeType=friendlyType />
<#if safeType=="byte[]"><#assign safeType="ByteArray" /></#if>
diff --git a/java/vector/src/main/codegen/templates/UnionReader.java
b/java/vector/src/main/codegen/templates/UnionReader.java
index f9e8859..bfb6f19 100644
--- a/java/vector/src/main/codegen/templates/UnionReader.java
+++ b/java/vector/src/main/codegen/templates/UnionReader.java
@@ -131,9 +131,9 @@ public class UnionReader extends AbstractFieldReader {
writer.data.copyFrom(idx(), writer.idx(), data);
}
- <#list ["Object", "Integer", "Long", "Boolean",
- "Character", "LocalDateTime", "Double", "Float",
- "Text", "Byte", "Short", "byte[]"] as friendlyType>
+ <#list ["Object", "BigDecimal", "Short", "Integer", "Long", "Boolean",
+ "LocalDateTime", "Duration", "Period", "Double", "Float",
+ "Character", "Text", "Byte", "byte[]"] as friendlyType>
<#assign safeType=friendlyType />
<#if safeType=="byte[]"><#assign safeType="ByteArray" /></#if>
diff --git
a/java/vector/src/main/java/org/apache/arrow/vector/DateMilliVector.java
b/java/vector/src/main/java/org/apache/arrow/vector/DateMilliVector.java
index 4736fba..fdd832c 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/DateMilliVector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/DateMilliVector.java
@@ -17,6 +17,8 @@
package org.apache.arrow.vector;
+import java.time.LocalDateTime;
+
import org.apache.arrow.memory.BufferAllocator;
import org.apache.arrow.vector.complex.impl.DateMilliReaderImpl;
import org.apache.arrow.vector.complex.reader.FieldReader;
@@ -24,8 +26,8 @@ import org.apache.arrow.vector.holders.DateMilliHolder;
import org.apache.arrow.vector.holders.NullableDateMilliHolder;
import org.apache.arrow.vector.types.Types.MinorType;
import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.DateUtility;
import org.apache.arrow.vector.util.TransferPair;
-import org.joda.time.LocalDateTime;
import io.netty.buffer.ArrowBuf;
@@ -130,9 +132,7 @@ public class DateMilliVector extends BaseFixedWidthVector {
return null;
} else {
final long millis = valueBuffer.getLong(index * TYPE_WIDTH);
- final LocalDateTime localDateTime = new
org.joda.time.LocalDateTime(millis,
- org.joda.time.DateTimeZone.UTC);
- return localDateTime;
+ return DateUtility.getLocalDateTimeFromEpochMilli(millis);
}
}
diff --git
a/java/vector/src/main/java/org/apache/arrow/vector/IntervalDayVector.java
b/java/vector/src/main/java/org/apache/arrow/vector/IntervalDayVector.java
index 4c65427..2dcc986 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/IntervalDayVector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/IntervalDayVector.java
@@ -17,6 +17,8 @@
package org.apache.arrow.vector;
+import java.time.Duration;
+
import org.apache.arrow.memory.BufferAllocator;
import org.apache.arrow.vector.complex.impl.IntervalDayReaderImpl;
import org.apache.arrow.vector.complex.reader.FieldReader;
@@ -25,7 +27,6 @@ import
org.apache.arrow.vector.holders.NullableIntervalDayHolder;
import org.apache.arrow.vector.types.Types.MinorType;
import org.apache.arrow.vector.types.pojo.FieldType;
import org.apache.arrow.vector.util.TransferPair;
-import org.joda.time.Period;
import io.netty.buffer.ArrowBuf;
@@ -130,15 +131,14 @@ public class IntervalDayVector extends
BaseFixedWidthVector {
* @param index position of element
* @return element at given index
*/
- public Period getObject(int index) {
+ public Duration getObject(int index) {
if (isSet(index) == 0) {
return null;
} else {
final int startIndex = index * TYPE_WIDTH;
final int days = valueBuffer.getInt(startIndex);
final int milliseconds = valueBuffer.getInt(startIndex +
MILLISECOND_OFFSET);
- final Period p = new Period();
- return p.plusDays(days).plusMillis(milliseconds);
+ return Duration.ofDays(days).plusMillis(milliseconds);
}
}
diff --git
a/java/vector/src/main/java/org/apache/arrow/vector/IntervalYearVector.java
b/java/vector/src/main/java/org/apache/arrow/vector/IntervalYearVector.java
index 8562e12..1de643b 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/IntervalYearVector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/IntervalYearVector.java
@@ -17,6 +17,8 @@
package org.apache.arrow.vector;
+import java.time.Period;
+
import org.apache.arrow.memory.BufferAllocator;
import org.apache.arrow.vector.complex.impl.IntervalYearReaderImpl;
import org.apache.arrow.vector.complex.reader.FieldReader;
@@ -25,7 +27,6 @@ import
org.apache.arrow.vector.holders.NullableIntervalYearHolder;
import org.apache.arrow.vector.types.Types.MinorType;
import org.apache.arrow.vector.types.pojo.FieldType;
import org.apache.arrow.vector.util.TransferPair;
-import org.joda.time.Period;
/**
* IntervalYearVector implements a fixed width (4 bytes) vector of
@@ -129,10 +130,8 @@ public class IntervalYearVector extends
BaseFixedWidthVector {
return null;
} else {
final int interval = valueBuffer.getInt(index * TYPE_WIDTH);
- final int years = (interval /
org.apache.arrow.vector.util.DateUtility.yearsToMonths);
- final int months = (interval %
org.apache.arrow.vector.util.DateUtility.yearsToMonths);
- final Period p = new Period();
- return p.plusYears(years).plusMonths(months);
+ // TODO: verify interval is in months
+ return Period.ofMonths(interval);
}
}
diff --git
a/java/vector/src/main/java/org/apache/arrow/vector/TimeMilliVector.java
b/java/vector/src/main/java/org/apache/arrow/vector/TimeMilliVector.java
index 83cde52..d7aa927 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/TimeMilliVector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/TimeMilliVector.java
@@ -17,6 +17,8 @@
package org.apache.arrow.vector;
+import java.time.LocalDateTime;
+
import org.apache.arrow.memory.BufferAllocator;
import org.apache.arrow.vector.complex.impl.TimeMilliReaderImpl;
import org.apache.arrow.vector.complex.reader.FieldReader;
@@ -24,8 +26,8 @@ import
org.apache.arrow.vector.holders.NullableTimeMilliHolder;
import org.apache.arrow.vector.holders.TimeMilliHolder;
import org.apache.arrow.vector.types.Types.MinorType;
import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.DateUtility;
import org.apache.arrow.vector.util.TransferPair;
-import org.joda.time.LocalDateTime;
import io.netty.buffer.ArrowBuf;
@@ -129,9 +131,9 @@ public class TimeMilliVector extends BaseFixedWidthVector {
if (isSet(index) == 0) {
return null;
}
- org.joda.time.LocalDateTime ldt = new
org.joda.time.LocalDateTime(get(index),
- org.joda.time.DateTimeZone.UTC);
- return ldt;
+ final int millis = valueBuffer.getInt(index * TYPE_WIDTH);
+ // TODO: this doesn't seem right, time not from epoch
+ return DateUtility.getLocalDateTimeFromEpochMilli(millis);
}
/**
diff --git
a/java/vector/src/main/java/org/apache/arrow/vector/TimeStampMicroVector.java
b/java/vector/src/main/java/org/apache/arrow/vector/TimeStampMicroVector.java
index 3e0273c..ea71fb7 100644
---
a/java/vector/src/main/java/org/apache/arrow/vector/TimeStampMicroVector.java
+++
b/java/vector/src/main/java/org/apache/arrow/vector/TimeStampMicroVector.java
@@ -17,6 +17,9 @@
package org.apache.arrow.vector;
+import java.time.LocalDateTime;
+import java.time.temporal.ChronoUnit;
+
import org.apache.arrow.memory.BufferAllocator;
import org.apache.arrow.vector.complex.impl.TimeStampMicroReaderImpl;
import org.apache.arrow.vector.complex.reader.FieldReader;
@@ -24,8 +27,8 @@ import
org.apache.arrow.vector.holders.NullableTimeStampMicroHolder;
import org.apache.arrow.vector.holders.TimeStampMicroHolder;
import org.apache.arrow.vector.types.Types.MinorType;
import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.DateUtility;
import org.apache.arrow.vector.util.TransferPair;
-import org.joda.time.LocalDateTime;
/**
* TimeStampMicroVector implements a fixed width vector (8 bytes) of
@@ -114,12 +117,8 @@ public class TimeStampMicroVector extends TimeStampVector {
if (isSet(index) == 0) {
return null;
} else {
- /* value is truncated when converting microseconds to milliseconds in
order to use DateTime type */
final long micros = valueBuffer.getLong(index * TYPE_WIDTH);
- final long millis =
java.util.concurrent.TimeUnit.MICROSECONDS.toMillis(micros);
- final org.joda.time.LocalDateTime localDateTime = new
org.joda.time.LocalDateTime(millis,
- org.joda.time.DateTimeZone.UTC);
- return localDateTime;
+ return DateUtility.getLocalDateTimeFromEpochMicro(micros);
}
}
diff --git
a/java/vector/src/main/java/org/apache/arrow/vector/TimeStampMilliVector.java
b/java/vector/src/main/java/org/apache/arrow/vector/TimeStampMilliVector.java
index d28b735..b05749e 100644
---
a/java/vector/src/main/java/org/apache/arrow/vector/TimeStampMilliVector.java
+++
b/java/vector/src/main/java/org/apache/arrow/vector/TimeStampMilliVector.java
@@ -17,6 +17,8 @@
package org.apache.arrow.vector;
+import java.time.LocalDateTime;
+
import org.apache.arrow.memory.BufferAllocator;
import org.apache.arrow.vector.complex.impl.TimeStampMilliReaderImpl;
import org.apache.arrow.vector.complex.reader.FieldReader;
@@ -24,8 +26,8 @@ import
org.apache.arrow.vector.holders.NullableTimeStampMilliHolder;
import org.apache.arrow.vector.holders.TimeStampMilliHolder;
import org.apache.arrow.vector.types.Types.MinorType;
import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.DateUtility;
import org.apache.arrow.vector.util.TransferPair;
-import org.joda.time.LocalDateTime;
/**
* TimeStampMilliVector implements a fixed width vector (8 bytes) of
@@ -115,9 +117,7 @@ public class TimeStampMilliVector extends TimeStampVector {
return null;
} else {
final long millis = valueBuffer.getLong(index * TYPE_WIDTH);
- final org.joda.time.LocalDateTime localDateTime = new
org.joda.time.LocalDateTime(millis,
- org.joda.time.DateTimeZone.UTC);
- return localDateTime;
+ return DateUtility.getLocalDateTimeFromEpochMilli(millis);
}
}
diff --git
a/java/vector/src/main/java/org/apache/arrow/vector/TimeStampNanoVector.java
b/java/vector/src/main/java/org/apache/arrow/vector/TimeStampNanoVector.java
index 77ba527..ccc17de 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/TimeStampNanoVector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/TimeStampNanoVector.java
@@ -17,6 +17,8 @@
package org.apache.arrow.vector;
+import java.time.LocalDateTime;
+
import org.apache.arrow.memory.BufferAllocator;
import org.apache.arrow.vector.complex.impl.TimeStampNanoReaderImpl;
import org.apache.arrow.vector.complex.reader.FieldReader;
@@ -24,8 +26,8 @@ import
org.apache.arrow.vector.holders.NullableTimeStampNanoHolder;
import org.apache.arrow.vector.holders.TimeStampNanoHolder;
import org.apache.arrow.vector.types.Types.MinorType;
import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.DateUtility;
import org.apache.arrow.vector.util.TransferPair;
-import org.joda.time.LocalDateTime;
/**
* TimeStampNanoVector implements a fixed width vector (8 bytes) of
@@ -115,10 +117,7 @@ public class TimeStampNanoVector extends TimeStampVector {
return null;
} else {
final long nanos = valueBuffer.getLong(index * TYPE_WIDTH);
- final long millis =
java.util.concurrent.TimeUnit.NANOSECONDS.toMillis(nanos);
- final org.joda.time.LocalDateTime localDateTime = new
org.joda.time.LocalDateTime(millis,
- org.joda.time.DateTimeZone.UTC);
- return localDateTime;
+ return DateUtility.getLocalDateTimeFromEpochNano(nanos);
}
}
diff --git
a/java/vector/src/main/java/org/apache/arrow/vector/TimeStampSecVector.java
b/java/vector/src/main/java/org/apache/arrow/vector/TimeStampSecVector.java
index 51e1f70..2293c10 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/TimeStampSecVector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/TimeStampSecVector.java
@@ -17,6 +17,8 @@
package org.apache.arrow.vector;
+import java.time.LocalDateTime;
+
import org.apache.arrow.memory.BufferAllocator;
import org.apache.arrow.vector.complex.impl.TimeStampSecReaderImpl;
import org.apache.arrow.vector.complex.reader.FieldReader;
@@ -24,8 +26,8 @@ import
org.apache.arrow.vector.holders.NullableTimeStampSecHolder;
import org.apache.arrow.vector.holders.TimeStampSecHolder;
import org.apache.arrow.vector.types.Types.MinorType;
import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.DateUtility;
import org.apache.arrow.vector.util.TransferPair;
-import org.joda.time.LocalDateTime;
/**
* TimeStampSecVector implements a fixed width vector (8 bytes) of
@@ -116,9 +118,7 @@ public class TimeStampSecVector extends TimeStampVector {
} else {
final long secs = valueBuffer.getLong(index * TYPE_WIDTH);
final long millis = java.util.concurrent.TimeUnit.SECONDS.toMillis(secs);
- final org.joda.time.LocalDateTime localDateTime = new
org.joda.time.LocalDateTime(millis,
- org.joda.time.DateTimeZone.UTC);
- return localDateTime;
+ return DateUtility.getLocalDateTimeFromEpochMilli(millis);
}
}
diff --git
a/java/vector/src/main/java/org/apache/arrow/vector/util/DateUtility.java
b/java/vector/src/main/java/org/apache/arrow/vector/util/DateUtility.java
index 3eeda2c..5fa806a 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/util/DateUtility.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/util/DateUtility.java
@@ -17,14 +17,12 @@
package org.apache.arrow.vector.util;
-import org.joda.time.DateTimeZone;
-import org.joda.time.LocalDateTime;
-import org.joda.time.LocalDateTimes;
-import org.joda.time.Period;
-import org.joda.time.format.DateTimeFormat;
-import org.joda.time.format.DateTimeFormatter;
-import org.joda.time.format.DateTimeFormatterBuilder;
-import org.joda.time.format.DateTimeParser;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
+import java.time.temporal.ChronoUnit;
import com.carrotsearch.hppc.ObjectIntHashMap;
@@ -620,10 +618,10 @@ public class DateUtility {
}
}
- public static final DateTimeFormatter formatDate =
DateTimeFormat.forPattern("yyyy-MM-dd");
- public static final DateTimeFormatter formatTimeStampMilli =
DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss.SSS");
- public static final DateTimeFormatter formatTimeStampTZ =
DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss.SSS ZZZ");
- public static final DateTimeFormatter formatTime =
DateTimeFormat.forPattern("HH:mm:ss.SSS");
+ public static final DateTimeFormatter formatDate =
DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ public static final DateTimeFormatter formatTimeStampMilli =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
+ public static final DateTimeFormatter formatTimeStampTZ =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS ZZZ");
+ public static final DateTimeFormatter formatTime =
DateTimeFormatter.ofPattern("HH:mm:ss.SSS");
public static DateTimeFormatter dateTimeTZFormat = null;
public static DateTimeFormatter timeFormat = null;
@@ -649,10 +647,10 @@ public class DateUtility {
public static DateTimeFormatter getDateTimeFormatter() {
if (dateTimeTZFormat == null) {
- DateTimeFormatter dateFormatter =
DateTimeFormat.forPattern("yyyy-MM-dd");
- DateTimeParser optionalTime = DateTimeFormat.forPattern("
HH:mm:ss").getParser();
- DateTimeParser optionalSec =
DateTimeFormat.forPattern(".SSS").getParser();
- DateTimeParser optionalZone = DateTimeFormat.forPattern("
ZZZ").getParser();
+ DateTimeFormatter dateFormatter =
DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ DateTimeFormatter optionalTime = DateTimeFormatter.ofPattern("
HH:mm:ss");
+ DateTimeFormatter optionalSec = DateTimeFormatter.ofPattern(".SSS");
+ DateTimeFormatter optionalZone = DateTimeFormatter.ofPattern(" ZZZ");
dateTimeTZFormat = new
DateTimeFormatterBuilder().append(dateFormatter).appendOptional(optionalTime)
.appendOptional(optionalSec).appendOptional(optionalZone).toFormatter();
@@ -664,29 +662,46 @@ public class DateUtility {
// Function returns time formatter used to parse time strings
public static DateTimeFormatter getTimeFormatter() {
if (timeFormat == null) {
- DateTimeFormatter timeFormatter = DateTimeFormat.forPattern("HH:mm:ss");
- DateTimeParser optionalSec =
DateTimeFormat.forPattern(".SSS").getParser();
+ DateTimeFormatter timeFormatter =
DateTimeFormatter.ofPattern("HH:mm:ss");
+ DateTimeFormatter optionalSec = DateTimeFormatter.ofPattern(".SSS");
timeFormat = new
DateTimeFormatterBuilder().append(timeFormatter).appendOptional(optionalSec).toFormatter();
}
return timeFormat;
}
- public static int monthsFromPeriod(Period period) {
- return (period.getYears() * yearsToMonths) + period.getMonths();
- }
-
- public static int millisFromPeriod(final Period period) {
- return (period.getHours() * hoursToMillis) +
- (period.getMinutes() * minutesToMillis) +
- (period.getSeconds() * secondsToMillis) +
- (period.getMillis());
+ /**
+ * Convert milliseconds from epoch to a LocalDateTime with UTC offset.
+ *
+ * @param epochMillis milliseconds from epoch
+ * @return LocalDateTime object with UTC offset
+ */
+ public static LocalDateTime getLocalDateTimeFromEpochMilli(long epochMillis)
{
+ final LocalDateTime localDateTime = LocalDateTime.ofInstant(
+ Instant.ofEpochMilli(epochMillis), ZoneOffset.UTC.normalized());
+ return localDateTime;
}
- public static long toMillis(LocalDateTime localDateTime) {
- return LocalDateTimes.getLocalMillis(localDateTime);
+ /**
+ * Convert microseconds from epoch to a LocalDateTime with UTC offset.
+ *
+ * @param epochMicros microseconds from epoch
+ * @return LocalDateTime object with UTC offset
+ */
+ public static LocalDateTime getLocalDateTimeFromEpochMicro(long epochMicros)
{
+ final long millis =
java.util.concurrent.TimeUnit.MICROSECONDS.toMillis(epochMicros);
+ final long addl_micros = epochMicros - (millis * 1000);
+ return
DateUtility.getLocalDateTimeFromEpochMilli(millis).plus(addl_micros,
ChronoUnit.MICROS);
}
- public static int toMillisOfDay(final LocalDateTime localDateTime) {
- return localDateTime.toDateTime(DateTimeZone.UTC).millisOfDay().get();
+ /**
+ * Convert nanoseconds from epoch to a LocalDateTime with UTC offset.
+ *
+ * @param epochNanos nanoseconds from epoch
+ * @return LocalDateTime object with UTC offset
+ */
+ public static LocalDateTime getLocalDateTimeFromEpochNano(long epochNanos) {
+ final long millis =
java.util.concurrent.TimeUnit.NANOSECONDS.toMillis(epochNanos);
+ final long addl_nanos = epochNanos - (millis * 1000 * 1000);
+ return
DateUtility.getLocalDateTimeFromEpochMilli(millis).plusNanos(addl_nanos);
}
}
diff --git a/java/vector/src/main/java/org/joda/time/LocalDateTimes.java
b/java/vector/src/main/java/org/joda/time/LocalDateTimes.java
deleted file mode 100644
index a80cd1f..0000000
--- a/java/vector/src/main/java/org/joda/time/LocalDateTimes.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.joda.time;
-
-/**
- * Workaround to access package protected fields in JODA.
- */
-public class LocalDateTimes {
-
- public static long getLocalMillis(LocalDateTime localDateTime) {
- return localDateTime.getLocalMillis();
- }
-
-}
diff --git
a/java/vector/src/test/java/org/apache/arrow/vector/TestCopyFrom.java
b/java/vector/src/test/java/org/apache/arrow/vector/TestCopyFrom.java
index 08932ef..9419ef7 100644
--- a/java/vector/src/test/java/org/apache/arrow/vector/TestCopyFrom.java
+++ b/java/vector/src/test/java/org/apache/arrow/vector/TestCopyFrom.java
@@ -23,11 +23,12 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import java.math.BigDecimal;
+import java.time.Duration;
+import java.time.Period;
import org.apache.arrow.memory.BufferAllocator;
import org.apache.arrow.memory.RootAllocator;
import org.apache.arrow.vector.types.Types.MinorType;
-import org.joda.time.Period;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -575,9 +576,9 @@ public class TestCopyFrom {
if ((i & 1) == 0) {
assertNull(vector1.getObject(i));
} else {
- final Period p = vector1.getObject(i);
- assertEquals(days + i, p.getDays());
- assertEquals(milliseconds + i, p.getMillis());
+ final Duration d = vector1.getObject(i);
+ assertEquals(days + i, d.toDays());
+ assertEquals(milliseconds + i, d.minusDays(days + i).toMillis());
}
}
@@ -604,9 +605,9 @@ public class TestCopyFrom {
if (((i & 1) == 0) || (i >= initialCapacity)) {
assertNull(vector2.getObject(i));
} else {
- final Period p = vector2.getObject(i);
- assertEquals(days + i, p.getDays());
- assertEquals(milliseconds + i, p.getMillis());
+ final Duration d = vector2.getObject(i);
+ assertEquals(days + i, d.toDays());
+ assertEquals(milliseconds + i, d.minusDays(days + i).toMillis());
}
}
}
@@ -629,11 +630,9 @@ public class TestCopyFrom {
continue;
}
vector1.setSafe(i, interval + i);
- final Period p = new Period();
final int years = (interval + i) /
org.apache.arrow.vector.util.DateUtility.yearsToMonths;
final int months = (interval + i) %
org.apache.arrow.vector.util.DateUtility.yearsToMonths;
- periods[i] = p.plusYears(years).plusMonths(months);
- ;
+ periods[i] = Period.ofYears(years).plusMonths(months).normalized();
}
vector1.setValueCount(initialCapacity);
@@ -648,7 +647,7 @@ public class TestCopyFrom {
if ((i & 1) == 0) {
assertNull(vector1.getObject(i));
} else {
- final Period p = vector1.getObject(i);
+ final Period p = vector1.getObject(i).normalized();
assertEquals(interval + i, vector1.get(i));
assertEquals(periods[i], p);
}
@@ -677,7 +676,7 @@ public class TestCopyFrom {
if (((i & 1) == 0) || (i >= initialCapacity)) {
assertNull(vector2.getObject(i));
} else {
- final Period p = vector2.getObject(i);
+ final Period p = vector2.getObject(i).normalized();
assertEquals(periods[i], p);
}
}
diff --git
a/java/vector/src/test/java/org/apache/arrow/vector/complex/writer/TestComplexWriter.java
b/java/vector/src/test/java/org/apache/arrow/vector/complex/writer/TestComplexWriter.java
index 61c1b92..d67fd6e 100644
---
a/java/vector/src/test/java/org/apache/arrow/vector/complex/writer/TestComplexWriter.java
+++
b/java/vector/src/test/java/org/apache/arrow/vector/complex/writer/TestComplexWriter.java
@@ -20,6 +20,7 @@ package org.apache.arrow.vector.complex.writer;
import static org.junit.Assert.*;
import java.math.BigDecimal;
+import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -70,7 +71,6 @@ import org.apache.arrow.vector.util.JsonStringArrayList;
import org.apache.arrow.vector.util.JsonStringHashMap;
import org.apache.arrow.vector.util.Text;
import org.apache.arrow.vector.util.TransferPair;
-import org.joda.time.LocalDateTime;
import org.junit.Assert;
import org.junit.Test;
@@ -654,7 +654,7 @@ public class TestComplexWriter {
public void timeStampSecWriter() throws Exception {
// test values
final long expectedSecs = 981173106L;
- final LocalDateTime expectedSecDateTime = new LocalDateTime(2001, 2, 3, 4,
5, 6, 0);
+ final LocalDateTime expectedSecDateTime = LocalDateTime.of(2001, 2, 3, 4,
5, 6, 0);
// write
NonNullableStructVector parent = NonNullableStructVector.empty("parent",
allocator);
@@ -698,7 +698,7 @@ public class TestComplexWriter {
public void timeStampMilliWriters() throws Exception {
// test values
final long expectedMillis = 981173106123L;
- final LocalDateTime expectedMilliDateTime = new LocalDateTime(2001, 2, 3,
4, 5, 6, 123);
+ final LocalDateTime expectedMilliDateTime = LocalDateTime.of(2001, 2, 3,
4, 5, 6, 123 * 1_000_000);
// write
NonNullableStructVector parent = NonNullableStructVector.empty("parent",
allocator);
@@ -754,7 +754,7 @@ public class TestComplexWriter {
public void timeStampMicroWriters() throws Exception {
// test values
final long expectedMicros = 981173106123456L;
- final LocalDateTime expectedMicroDateTime = new LocalDateTime(2001, 2, 3,
4, 5, 6, 123);
+ final LocalDateTime expectedMicroDateTime = LocalDateTime.of(2001, 2, 3,
4, 5, 6, 123456 * 1000);
// write
NonNullableStructVector parent = NonNullableStructVector.empty("parent",
allocator);
@@ -801,7 +801,7 @@ public class TestComplexWriter {
public void timeStampNanoWriters() throws Exception {
// test values
final long expectedNanos = 981173106123456789L;
- final LocalDateTime expectedNanoDateTime = new LocalDateTime(2001, 2, 3,
4, 5, 6, 123);
+ final LocalDateTime expectedNanoDateTime = LocalDateTime.of(2001, 2, 3, 4,
5, 6, 123456789);
// write
NonNullableStructVector parent = NonNullableStructVector.empty("parent",
allocator);
diff --git
a/java/vector/src/test/java/org/apache/arrow/vector/ipc/BaseFileTest.java
b/java/vector/src/test/java/org/apache/arrow/vector/ipc/BaseFileTest.java
index 059dcb0..e724293 100644
--- a/java/vector/src/test/java/org/apache/arrow/vector/ipc/BaseFileTest.java
+++ b/java/vector/src/test/java/org/apache/arrow/vector/ipc/BaseFileTest.java
@@ -25,6 +25,10 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
import java.util.Arrays;
import java.util.List;
@@ -54,6 +58,7 @@ import org.apache.arrow.vector.complex.writer.IntWriter;
import org.apache.arrow.vector.complex.writer.TimeMilliWriter;
import org.apache.arrow.vector.complex.writer.TimeStampMilliTZWriter;
import org.apache.arrow.vector.complex.writer.TimeStampMilliWriter;
+import org.apache.arrow.vector.complex.writer.TimeStampNanoWriter;
import org.apache.arrow.vector.dictionary.Dictionary;
import org.apache.arrow.vector.dictionary.DictionaryEncoder;
import org.apache.arrow.vector.dictionary.DictionaryProvider;
@@ -62,10 +67,7 @@ import org.apache.arrow.vector.types.pojo.ArrowType;
import org.apache.arrow.vector.types.pojo.DictionaryEncoding;
import org.apache.arrow.vector.types.pojo.Field;
import org.apache.arrow.vector.types.pojo.FieldType;
-import org.apache.arrow.vector.util.DateUtility;
import org.apache.arrow.vector.util.Text;
-import org.joda.time.DateTimeZone;
-import org.joda.time.LocalDateTime;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
@@ -82,18 +84,14 @@ public class BaseFileTest {
protected static final int COUNT = 10;
protected BufferAllocator allocator;
- private DateTimeZone defaultTimezone = DateTimeZone.getDefault();
-
@Before
public void init() {
- DateTimeZone.setDefault(DateTimeZone.forOffsetHours(2));
allocator = new RootAllocator(Integer.MAX_VALUE);
}
@After
public void tearDown() {
allocator.close();
- DateTimeZone.setDefault(defaultTimezone);
}
protected void writeData(int count, StructVector parent) {
@@ -188,7 +186,7 @@ public class BaseFileTest {
}
private LocalDateTime makeDateTimeFromCount(int i) {
- return new LocalDateTime(2000 + i, 1 + i, 1 + i, i, i, i, i);
+ return LocalDateTime.of(2000 + i, 1 + i, 1 + i, i, i, i, i * 100_000_000 +
i);
}
protected void writeDateTimeData(int count, StructVector parent) {
@@ -199,20 +197,27 @@ public class BaseFileTest {
TimeMilliWriter timeWriter = rootWriter.timeMilli("time");
TimeStampMilliWriter timeStampMilliWriter =
rootWriter.timeStampMilli("timestamp-milli");
TimeStampMilliTZWriter timeStampMilliTZWriter =
rootWriter.timeStampMilliTZ("timestamp-milliTZ", "Europe/Paris");
+ TimeStampNanoWriter timeStampNanoWriter =
rootWriter.timeStampNano("timestamp-nano");
for (int i = 0; i < count; i++) {
LocalDateTime dt = makeDateTimeFromCount(i);
// Number of days in milliseconds since epoch, stored as 64-bit integer,
only date part is used
dateWriter.setPosition(i);
- long dateLong =
DateUtility.toMillis(dt.minusMillis(dt.getMillisOfDay()));
+ long dateLong =
dt.toLocalDate().atStartOfDay().toInstant(ZoneOffset.UTC).toEpochMilli();
dateWriter.writeDateMilli(dateLong);
// Time is a value in milliseconds since midnight, stored as 32-bit
integer
timeWriter.setPosition(i);
- timeWriter.writeTimeMilli(dt.getMillisOfDay());
- // Timestamp is milliseconds since the epoch, stored as 64-bit integer
+ int milliOfDay = (int)
java.util.concurrent.TimeUnit.NANOSECONDS.toMillis(dt.toLocalTime().toNanoOfDay());
+ timeWriter.writeTimeMilli(milliOfDay);
+ // Timestamp as milliseconds since the epoch, stored as 64-bit integer
timeStampMilliWriter.setPosition(i);
- timeStampMilliWriter.writeTimeStampMilli(DateUtility.toMillis(dt));
+
timeStampMilliWriter.writeTimeStampMilli(dt.toInstant(ZoneOffset.UTC).toEpochMilli());
+ // Timestamp as milliseconds since epoch with timezone
timeStampMilliTZWriter.setPosition(i);
- timeStampMilliTZWriter.writeTimeStampMilliTZ(DateUtility.toMillis(dt));
+
timeStampMilliTZWriter.writeTimeStampMilliTZ(dt.atZone(ZoneId.of("Europe/Paris")).toInstant().toEpochMilli());
+ // Timestamp as nanoseconds since epoch
+ timeStampNanoWriter.setPosition(i);
+ long tsNanos = dt.toInstant(ZoneOffset.UTC).toEpochMilli() * 1_000_000 +
i; // need to add back in nano val
+ timeStampNanoWriter.writeTimeStampNano(tsNanos);
}
writer.setValueCount(count);
}
@@ -221,16 +226,19 @@ public class BaseFileTest {
Assert.assertEquals(count, root.getRowCount());
printVectors(root.getFieldVectors());
for (int i = 0; i < count; i++) {
- long dateVal = ((DateMilliVector) root.getVector("date")).get(i);
LocalDateTime dt = makeDateTimeFromCount(i);
- LocalDateTime dateExpected = dt.minusMillis(dt.getMillisOfDay());
- Assert.assertEquals(DateUtility.toMillis(dateExpected), dateVal);
- long timeVal = ((TimeMilliVector) root.getVector("time")).get(i);
- Assert.assertEquals(dt.getMillisOfDay(), timeVal);
+ LocalDateTime dtMilli = dt.minusNanos(i);
+ LocalDateTime dateVal = ((DateMilliVector)
root.getVector("date")).getObject(i);
+ LocalDateTime dateExpected = dt.toLocalDate().atStartOfDay();
+ Assert.assertEquals(dateExpected, dateVal);
+ LocalTime timeVal = ((TimeMilliVector)
root.getVector("time")).getObject(i).toLocalTime();
+ Assert.assertEquals(dtMilli.toLocalTime(), timeVal);
Object timestampMilliVal =
root.getVector("timestamp-milli").getObject(i);
- Assert.assertEquals(dt, timestampMilliVal);
+ Assert.assertEquals(dtMilli, timestampMilliVal);
Object timestampMilliTZVal =
root.getVector("timestamp-milliTZ").getObject(i);
- Assert.assertEquals(DateUtility.toMillis(dt), timestampMilliTZVal);
+
Assert.assertEquals(dt.atZone(ZoneId.of("Europe/Paris")).toInstant().toEpochMilli(),
timestampMilliTZVal);
+ Object timestampNanoVal = root.getVector("timestamp-nano").getObject(i);
+ Assert.assertEquals(dt, timestampNanoVal);
}
}