Skip to content

Commit f5774bf

Browse files
authored
Use Avatica DateTimeUtils for getString in Date/Time (#7)
* Make UTC the default tz instead of using local tz * Use Avatica DateTimeUtils for getString in Date/Time/TimeStamp * Correct usage for unix*ToString * Add unit tests for Date/Time getString * Check wasNull
1 parent e60a4d8 commit f5774bf

5 files changed

Lines changed: 89 additions & 7 deletions

File tree

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

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import static org.apache.arrow.driver.jdbc.accessor.impl.calendar.ArrowFlightJdbcDateVectorGetter.Getter;
2121
import static org.apache.arrow.driver.jdbc.accessor.impl.calendar.ArrowFlightJdbcDateVectorGetter.Holder;
2222
import static org.apache.arrow.driver.jdbc.accessor.impl.calendar.ArrowFlightJdbcDateVectorGetter.createGetter;
23+
import static org.apache.calcite.avatica.util.DateTimeUtils.MILLIS_PER_DAY;
24+
import static org.apache.calcite.avatica.util.DateTimeUtils.unixDateToString;
2325

2426
import java.sql.Date;
2527
import java.sql.Timestamp;
@@ -84,9 +86,7 @@ public Object getObject() {
8486

8587
@Override
8688
public Date getDate(Calendar calendar) {
87-
getter.get(getCurrentRow(), holder);
88-
this.wasNull = holder.isSet == 0;
89-
this.wasNullConsumer.setWasNull(this.wasNull);
89+
fillHolder();
9090
if (this.wasNull) {
9191
return null;
9292
}
@@ -97,6 +97,12 @@ public Date getDate(Calendar calendar) {
9797
return new Date(DateTimeUtils.applyCalendarOffset(milliseconds, calendar));
9898
}
9999

100+
private void fillHolder() {
101+
getter.get(getCurrentRow(), holder);
102+
this.wasNull = holder.isSet == 0;
103+
this.wasNullConsumer.setWasNull(this.wasNull);
104+
}
105+
100106
@Override
101107
public Timestamp getTimestamp(Calendar calendar) {
102108
Date date = getDate(calendar);
@@ -106,6 +112,16 @@ public Timestamp getTimestamp(Calendar calendar) {
106112
return new Timestamp(date.getTime());
107113
}
108114

115+
@Override
116+
public String getString() {
117+
fillHolder();
118+
if (wasNull) {
119+
return null;
120+
}
121+
long milliseconds = timeUnit.toMillis(holder.value);
122+
return unixDateToString((int) (milliseconds / MILLIS_PER_DAY));
123+
}
124+
109125
protected static TimeUnit getTimeUnitForVector(ValueVector vector) {
110126
if (vector instanceof DateDayVector) {
111127
return TimeUnit.DAYS;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ protected static TimeZone getTimeZoneForVector(TimeStampVector vector) {
177177

178178
String timezoneName = arrowType.getTimezone();
179179
if (timezoneName == null) {
180-
return TimeZone.getDefault();
180+
return TimeZone.getTimeZone("UTC");
181181
}
182182

183183
return TimeZone.getTimeZone(timezoneName);

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

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import static org.apache.arrow.driver.jdbc.accessor.impl.calendar.ArrowFlightJdbcTimeVectorGetter.Getter;
2121
import static org.apache.arrow.driver.jdbc.accessor.impl.calendar.ArrowFlightJdbcTimeVectorGetter.Holder;
2222
import static org.apache.arrow.driver.jdbc.accessor.impl.calendar.ArrowFlightJdbcTimeVectorGetter.createGetter;
23+
import static org.apache.calcite.avatica.util.DateTimeUtils.MILLIS_PER_DAY;
24+
import static org.apache.calcite.avatica.util.DateTimeUtils.unixTimeToString;
2325

2426
import java.sql.Time;
2527
import java.sql.Timestamp;
@@ -116,9 +118,7 @@ public Object getObject() {
116118

117119
@Override
118120
public Time getTime(Calendar calendar) {
119-
getter.get(getCurrentRow(), holder);
120-
this.wasNull = holder.isSet == 0;
121-
this.wasNullConsumer.setWasNull(this.wasNull);
121+
fillHolder();
122122
if (this.wasNull) {
123123
return null;
124124
}
@@ -129,6 +129,12 @@ public Time getTime(Calendar calendar) {
129129
return new Time(DateTimeUtils.applyCalendarOffset(milliseconds, calendar));
130130
}
131131

132+
private void fillHolder() {
133+
getter.get(getCurrentRow(), holder);
134+
this.wasNull = holder.isSet == 0;
135+
this.wasNullConsumer.setWasNull(this.wasNull);
136+
}
137+
132138
@Override
133139
public Timestamp getTimestamp(Calendar calendar) {
134140
Time time = getTime(calendar);
@@ -138,6 +144,16 @@ public Timestamp getTimestamp(Calendar calendar) {
138144
return new Timestamp(time.getTime());
139145
}
140146

147+
@Override
148+
public String getString() {
149+
fillHolder();
150+
if (wasNull) {
151+
return null;
152+
}
153+
long milliseconds = timeUnit.toMillis(holder.value);
154+
return unixTimeToString((int) (milliseconds % MILLIS_PER_DAY));
155+
}
156+
141157
protected static TimeUnit getTimeUnitForVector(ValueVector vector) {
142158
if (vector instanceof TimeNanoVector) {
143159
return TimeUnit.NANOSECONDS;

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import static org.apache.arrow.driver.jdbc.accessor.impl.calendar.ArrowFlightJdbcDateVectorAccessor.getTimeUnitForVector;
2121
import static org.hamcrest.CoreMatchers.equalTo;
2222
import static org.hamcrest.CoreMatchers.is;
23+
import static org.hamcrest.CoreMatchers.not;
2324

2425
import java.sql.Date;
2526
import java.sql.Timestamp;
@@ -205,6 +206,30 @@ public void testShouldGetStringBeConsistentWithVarCharAccessorWithCalendar() thr
205206
assertGetStringIsConsistentWithVarCharAccessor(calendar);
206207
}
207208

209+
@Test
210+
public void testValidateGetStringTimeZoneConsistency() throws Exception {
211+
accessorIterator.iterate(vector, (accessor, currentRow) -> {
212+
final TimeZone defaultTz = TimeZone.getDefault();
213+
try {
214+
final String string = accessor.getString(); // Should always be UTC as no calendar is provided
215+
216+
// Validate with UTC
217+
Date date = accessor.getDate(null);
218+
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
219+
collector.checkThat(date.toString(), is(string));
220+
221+
// Validate with different TZ
222+
TimeZone.setDefault(TimeZone.getTimeZone(AMERICA_VANCOUVER));
223+
collector.checkThat(date.toString(), not(string));
224+
225+
collector.checkThat(accessor.wasNull(), is(false));
226+
} finally {
227+
// Set default Tz back
228+
TimeZone.setDefault(defaultTz);
229+
}
230+
});
231+
}
232+
208233
private void assertGetStringIsConsistentWithVarCharAccessor(Calendar calendar) throws Exception {
209234
try (VarCharVector varCharVector = new VarCharVector("",
210235
rootAllocatorTestRule.getRootAllocator())) {

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import static org.apache.arrow.driver.jdbc.accessor.impl.calendar.ArrowFlightJdbcTimeVectorAccessor.getTimeUnitForVector;
2121
import static org.hamcrest.CoreMatchers.equalTo;
2222
import static org.hamcrest.CoreMatchers.is;
23+
import static org.hamcrest.CoreMatchers.not;
2324

2425
import java.sql.Time;
2526
import java.sql.Timestamp;
@@ -214,6 +215,30 @@ public void testShouldGetStringBeConsistentWithVarCharAccessorWithCalendar() thr
214215
assertGetStringIsConsistentWithVarCharAccessor(calendar);
215216
}
216217

218+
@Test
219+
public void testValidateGetStringTimeZoneConsistency() throws Exception {
220+
accessorIterator.iterate(vector, (accessor, currentRow) -> {
221+
final TimeZone defaultTz = TimeZone.getDefault();
222+
try {
223+
final String string = accessor.getString(); // Should always be UTC as no calendar is provided
224+
225+
// Validate with UTC
226+
Time time = accessor.getTime(null);
227+
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
228+
collector.checkThat(time.toString(), is(string));
229+
230+
// Validate with different TZ
231+
TimeZone.setDefault(TimeZone.getTimeZone(AMERICA_VANCOUVER));
232+
collector.checkThat(time.toString(), not(string));
233+
234+
collector.checkThat(accessor.wasNull(), is(false));
235+
} finally {
236+
// Set default Tz back
237+
TimeZone.setDefault(defaultTz);
238+
}
239+
});
240+
}
241+
217242
private void assertGetStringIsConsistentWithVarCharAccessor(Calendar calendar) throws Exception {
218243
try (VarCharVector varCharVector = new VarCharVector("",
219244
rootAllocatorTestRule.getRootAllocator())) {

0 commit comments

Comments
 (0)