Skip to content

Commit 7924e7b

Browse files
Merge pull request apache#29 from rafael-telles/Timestamp_fix
Timestamp fix
2 parents f6ac593 + 00808c0 commit 7924e7b

File tree

3 files changed

+32
-67
lines changed

3 files changed

+32
-67
lines changed

java/flight/flight-jdbc-driver/src/main/java/org/apache/arrow/driver/jdbc/accessor/impl/calendar/ArrowFlightJdbcTimeStampVectorAccessor.java

+21-54
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424
import java.sql.Date;
2525
import java.sql.Time;
2626
import java.sql.Timestamp;
27-
import java.time.LocalDateTime;
28-
import java.time.temporal.ChronoUnit;
2927
import java.util.Calendar;
3028
import java.util.TimeZone;
3129
import java.util.concurrent.TimeUnit;
@@ -35,7 +33,6 @@
3533
import org.apache.arrow.driver.jdbc.accessor.ArrowFlightJdbcAccessorFactory;
3634
import org.apache.arrow.vector.TimeStampVector;
3735
import org.apache.arrow.vector.types.pojo.ArrowType;
38-
import org.apache.arrow.vector.util.DateUtility;
3936

4037
/**
4138
* Accessor for the Arrow types extending from {@link TimeStampVector}.
@@ -45,16 +42,8 @@ public class ArrowFlightJdbcTimeStampVectorAccessor extends ArrowFlightJdbcAcces
4542
private final TimeZone timeZone;
4643
private final Getter getter;
4744
private final TimeUnit timeUnit;
48-
private final LongToLocalDateTime longToLocalDateTime;
4945
private final Holder holder;
5046

51-
/**
52-
* Functional interface used to convert a number (in any time resolution) to LocalDateTime.
53-
*/
54-
interface LongToLocalDateTime {
55-
LocalDateTime fromLong(long value);
56-
}
57-
5847
/**
5948
* Instantiate a ArrowFlightJdbcTimeStampVectorAccessor for given vector.
6049
*/
@@ -67,7 +56,6 @@ public ArrowFlightJdbcTimeStampVectorAccessor(TimeStampVector vector,
6756

6857
this.timeZone = getTimeZoneForVector(vector);
6958
this.timeUnit = getTimeUnitForVector(vector);
70-
this.longToLocalDateTime = getLongToLocalDateTimeForVector(vector, this.timeZone);
7159
}
7260

7361
@Override
@@ -80,55 +68,56 @@ public Object getObject() {
8068
return this.getTimestamp(null);
8169
}
8270

83-
private LocalDateTime getLocalDateTime(Calendar calendar) {
71+
private Long getLocalDateTimeMillis() {
8472
getter.get(getCurrentRow(), holder);
8573
this.wasNull = holder.isSet == 0;
8674
this.wasNullConsumer.setWasNull(this.wasNull);
8775
if (this.wasNull) {
8876
return null;
8977
}
9078

91-
long value = holder.value;
92-
93-
LocalDateTime localDateTime = this.longToLocalDateTime.fromLong(value);
79+
final long value = holder.value;
80+
final long millis = this.timeUnit.toMillis(value);
9481

95-
if (calendar != null) {
96-
TimeZone timeZone = calendar.getTimeZone();
97-
long millis = this.timeUnit.toMillis(value);
98-
localDateTime = localDateTime
99-
.minus(timeZone.getOffset(millis) - this.timeZone.getOffset(millis), ChronoUnit.MILLIS);
100-
}
101-
return localDateTime;
82+
return millis + this.timeZone.getOffset(millis);
10283
}
10384

10485
@Override
10586
public Date getDate(Calendar calendar) {
106-
LocalDateTime localDateTime = getLocalDateTime(calendar);
107-
if (localDateTime == null) {
87+
Long millis = getLocalDateTimeMillis();
88+
if (millis == null) {
10889
return null;
10990
}
11091

111-
return new Date(Timestamp.valueOf(localDateTime).getTime());
92+
return new Date(applyCalendarOffset(calendar, millis));
11293
}
11394

11495
@Override
11596
public Time getTime(Calendar calendar) {
116-
LocalDateTime localDateTime = getLocalDateTime(calendar);
117-
if (localDateTime == null) {
97+
Long millis = getLocalDateTimeMillis();
98+
if (millis == null) {
11899
return null;
119100
}
120101

121-
return new Time(Timestamp.valueOf(localDateTime).getTime());
102+
return new Time(applyCalendarOffset(calendar, millis));
122103
}
123104

124105
@Override
125106
public Timestamp getTimestamp(Calendar calendar) {
126-
LocalDateTime localDateTime = getLocalDateTime(calendar);
127-
if (localDateTime == null) {
107+
Long millis = getLocalDateTimeMillis();
108+
if (millis == null) {
128109
return null;
129110
}
130111

131-
return Timestamp.valueOf(localDateTime);
112+
return new Timestamp(applyCalendarOffset(calendar, millis));
113+
}
114+
115+
private long applyCalendarOffset(final Calendar calendar, final long millis) {
116+
if (calendar == null) {
117+
return millis - Calendar.getInstance(TimeZone.getDefault()).getTimeZone().getOffset(millis);
118+
}
119+
120+
return millis - calendar.getTimeZone().getOffset(millis) + this.timeZone.getOffset(millis);
132121
}
133122

134123
protected static TimeUnit getTimeUnitForVector(TimeStampVector vector) {
@@ -149,28 +138,6 @@ protected static TimeUnit getTimeUnitForVector(TimeStampVector vector) {
149138
}
150139
}
151140

152-
protected static LongToLocalDateTime getLongToLocalDateTimeForVector(TimeStampVector vector,
153-
TimeZone timeZone) {
154-
String timeZoneID = timeZone.getID();
155-
156-
ArrowType.Timestamp arrowType =
157-
(ArrowType.Timestamp) vector.getField().getFieldType().getType();
158-
159-
switch (arrowType.getUnit()) {
160-
case NANOSECOND:
161-
return nanoseconds -> DateUtility.getLocalDateTimeFromEpochNano(nanoseconds, timeZoneID);
162-
case MICROSECOND:
163-
return microseconds -> DateUtility.getLocalDateTimeFromEpochMicro(microseconds, timeZoneID);
164-
case MILLISECOND:
165-
return milliseconds -> DateUtility.getLocalDateTimeFromEpochMilli(milliseconds, timeZoneID);
166-
case SECOND:
167-
return seconds -> DateUtility.getLocalDateTimeFromEpochMilli(
168-
TimeUnit.SECONDS.toMillis(seconds), timeZoneID);
169-
default:
170-
throw new UnsupportedOperationException("Invalid Arrow time unit");
171-
}
172-
}
173-
174141
protected static TimeZone getTimeZoneForVector(TimeStampVector vector) {
175142
ArrowType.Timestamp arrowType =
176143
(ArrowType.Timestamp) vector.getField().getFieldType().getType();

java/flight/flight-jdbc-driver/src/main/java/org/apache/arrow/driver/jdbc/utils/DateTimeUtils.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package org.apache.arrow.driver.jdbc.utils;
1919

2020
import java.util.Calendar;
21+
import java.util.TimeZone;
2122

2223
/**
2324
* Datetime utility functions.
@@ -32,7 +33,7 @@ private DateTimeUtils() {
3233
*/
3334
public static long applyCalendarOffset(long milliseconds, Calendar calendar) {
3435
if (calendar == null) {
35-
return milliseconds;
36+
return milliseconds - Calendar.getInstance(TimeZone.getDefault()).getTimeZone().getOffset(milliseconds);
3637
}
3738
return milliseconds - calendar.getTimeZone().getOffset(milliseconds);
3839
}

java/flight/flight-jdbc-driver/src/test/java/org/apache/arrow/driver/jdbc/accessor/impl/calendar/ArrowFlightJdbcTimeStampVectorAccessorTest.java

+9-12
Original file line numberDiff line numberDiff line change
@@ -176,13 +176,12 @@ public void testShouldGetTimestampReturnValidTimestampWithCalendar() throws Exce
176176
TimeZone timeZoneForVector = getTimeZoneForVector(vector);
177177

178178
accessorIterator.iterate(vector, (accessor, currentRow) -> {
179-
final Timestamp resultWithoutCalendar = accessor.getTimestamp(null);
180179
final Timestamp result = accessor.getTimestamp(calendar);
181180

182-
long offset = timeZone.getOffset(resultWithoutCalendar.getTime()) -
183-
timeZoneForVector.getOffset(resultWithoutCalendar.getTime());
181+
long offset = timeZone.getOffset(result.getTime()) -
182+
timeZoneForVector.getOffset(result.getTime());
184183

185-
collector.checkThat(resultWithoutCalendar.getTime() - result.getTime(), is(offset));
184+
collector.checkThat(result.getTime(), is(getTimestampForVector(currentRow).getTime() - offset));
186185
collector.checkThat(accessor.wasNull(), is(false));
187186
});
188187
}
@@ -209,13 +208,12 @@ public void testShouldGetDateReturnValidDateWithCalendar() throws Exception {
209208
TimeZone timeZoneForVector = getTimeZoneForVector(vector);
210209

211210
accessorIterator.iterate(vector, (accessor, currentRow) -> {
212-
final Date resultWithoutCalendar = accessor.getDate(null);
213211
final Date result = accessor.getDate(calendar);
214212

215-
long offset = timeZone.getOffset(resultWithoutCalendar.getTime()) -
216-
timeZoneForVector.getOffset(resultWithoutCalendar.getTime());
213+
long offset = timeZone.getOffset(result.getTime()) -
214+
timeZoneForVector.getOffset(result.getTime());
217215

218-
collector.checkThat(resultWithoutCalendar.getTime() - result.getTime(), is(offset));
216+
collector.checkThat(result.getTime(), is(getTimestampForVector(currentRow).getTime() - offset ));
219217
collector.checkThat(accessor.wasNull(), is(false));
220218
});
221219
}
@@ -242,13 +240,12 @@ public void testShouldGetTimeReturnValidTimeWithCalendar() throws Exception {
242240
TimeZone timeZoneForVector = getTimeZoneForVector(vector);
243241

244242
accessorIterator.iterate(vector, (accessor, currentRow) -> {
245-
final Time resultWithoutCalendar = accessor.getTime(null);
246243
final Time result = accessor.getTime(calendar);
247244

248-
long offset = timeZone.getOffset(resultWithoutCalendar.getTime()) -
249-
timeZoneForVector.getOffset(resultWithoutCalendar.getTime());
245+
long offset = timeZone.getOffset(result.getTime()) -
246+
timeZoneForVector.getOffset(result.getTime());
250247

251-
collector.checkThat(resultWithoutCalendar.getTime() - result.getTime(), is(offset));
248+
collector.checkThat(result.getTime(), is(getTimestampForVector(currentRow).getTime() - offset ));
252249
collector.checkThat(accessor.wasNull(), is(false));
253250
});
254251
}

0 commit comments

Comments
 (0)