24
24
import java .sql .Date ;
25
25
import java .sql .Time ;
26
26
import java .sql .Timestamp ;
27
+ import java .time .LocalDateTime ;
28
+ import java .time .temporal .ChronoUnit ;
27
29
import java .util .Calendar ;
28
30
import java .util .TimeZone ;
29
31
import java .util .concurrent .TimeUnit ;
33
35
import org .apache .arrow .driver .jdbc .accessor .ArrowFlightJdbcAccessorFactory ;
34
36
import org .apache .arrow .vector .TimeStampVector ;
35
37
import org .apache .arrow .vector .types .pojo .ArrowType ;
38
+ import org .apache .arrow .vector .util .DateUtility ;
36
39
37
40
/**
38
41
* Accessor for the Arrow types extending from {@link TimeStampVector}.
@@ -42,8 +45,16 @@ public class ArrowFlightJdbcTimeStampVectorAccessor extends ArrowFlightJdbcAcces
42
45
private final TimeZone timeZone ;
43
46
private final Getter getter ;
44
47
private final TimeUnit timeUnit ;
48
+ private final LongToLocalDateTime longToLocalDateTime ;
45
49
private final Holder holder ;
46
50
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
+
47
58
/**
48
59
* Instantiate a ArrowFlightJdbcTimeStampVectorAccessor for given vector.
49
60
*/
@@ -56,6 +67,7 @@ public ArrowFlightJdbcTimeStampVectorAccessor(TimeStampVector vector,
56
67
57
68
this .timeZone = getTimeZoneForVector (vector );
58
69
this .timeUnit = getTimeUnitForVector (vector );
70
+ this .longToLocalDateTime = getLongToLocalDateTimeForVector (vector , this .timeZone );
59
71
}
60
72
61
73
@ Override
@@ -68,56 +80,55 @@ public Object getObject() {
68
80
return this .getTimestamp (null );
69
81
}
70
82
71
- private Long getLocalDateTimeMillis ( ) {
83
+ private LocalDateTime getLocalDateTime ( Calendar calendar ) {
72
84
getter .get (getCurrentRow (), holder );
73
85
this .wasNull = holder .isSet == 0 ;
74
86
this .wasNullConsumer .setWasNull (this .wasNull );
75
87
if (this .wasNull ) {
76
88
return null ;
77
89
}
78
90
79
- final long value = holder .value ;
80
- final long millis = this .timeUnit .toMillis (value );
91
+ long value = holder .value ;
92
+
93
+ LocalDateTime localDateTime = this .longToLocalDateTime .fromLong (value );
81
94
82
- return millis + this .timeZone .getOffset (millis );
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 ;
83
102
}
84
103
85
104
@ Override
86
105
public Date getDate (Calendar calendar ) {
87
- Long millis = getLocalDateTimeMillis ( );
88
- if (millis == null ) {
106
+ LocalDateTime localDateTime = getLocalDateTime ( calendar );
107
+ if (localDateTime == null ) {
89
108
return null ;
90
109
}
91
110
92
- return new Date (applyCalendarOffset ( calendar , millis ));
111
+ return new Date (Timestamp . valueOf ( localDateTime ). getTime ( ));
93
112
}
94
113
95
114
@ Override
96
115
public Time getTime (Calendar calendar ) {
97
- Long millis = getLocalDateTimeMillis ( );
98
- if (millis == null ) {
116
+ LocalDateTime localDateTime = getLocalDateTime ( calendar );
117
+ if (localDateTime == null ) {
99
118
return null ;
100
119
}
101
120
102
- return new Time (applyCalendarOffset ( calendar , millis ));
121
+ return new Time (Timestamp . valueOf ( localDateTime ). getTime ( ));
103
122
}
104
123
105
124
@ Override
106
125
public Timestamp getTimestamp (Calendar calendar ) {
107
- Long millis = getLocalDateTimeMillis ( );
108
- if (millis == null ) {
126
+ LocalDateTime localDateTime = getLocalDateTime ( calendar );
127
+ if (localDateTime == null ) {
109
128
return null ;
110
129
}
111
130
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 );
131
+ return Timestamp .valueOf (localDateTime );
121
132
}
122
133
123
134
protected static TimeUnit getTimeUnitForVector (TimeStampVector vector ) {
@@ -138,6 +149,28 @@ protected static TimeUnit getTimeUnitForVector(TimeStampVector vector) {
138
149
}
139
150
}
140
151
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
+
141
174
protected static TimeZone getTimeZoneForVector (TimeStampVector vector ) {
142
175
ArrowType .Timestamp arrowType =
143
176
(ArrowType .Timestamp ) vector .getField ().getFieldType ().getType ();
0 commit comments