Skip to content

[Bug] The Hive connector encounters time offset issues when reading and writing data of the timestamp with local time zone field type. #5571

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@
import org.apache.hadoop.hive.serde2.objectinspector.primitive.TimestampLocalTZObjectInspector;
import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoFactory;

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;

/**
* {@link AbstractPrimitiveJavaObjectInspector} for TIMESTAMP WITH LOCAL TIME ZONE type. The
Expand All @@ -45,7 +48,9 @@ public TimestampTZ getPrimitiveJavaObject(Object o) {
return null;
}

return new TimestampTZ(((Timestamp) o).toLocalDateTime().atZone(ZoneId.systemDefault()));
Instant instant = ((Timestamp) o).toLocalDateTime().toInstant(ZoneOffset.UTC);
ZonedDateTime zonedDateTime = instant.atZone(ZoneId.systemDefault());
return new TimestampTZ(zonedDateTime);
}

@Override
Expand All @@ -72,8 +77,12 @@ public Timestamp convert(Object value) {
return null;
}
if (value instanceof TimestampTZ) {
return Timestamp.fromLocalDateTime(
((TimestampTZ) value).getZonedDateTime().toLocalDateTime());
TimestampTZ timestampTZ = (TimestampTZ) value;
long millisecond =
timestampTZ.getEpochSecond() * 1000L
+ (long) (timestampTZ.getNanos() / 1000000);
int nanoOfMillisecond = timestampTZ.getNanos() % 1000000;
return Timestamp.fromEpochMillis(millisecond, nanoOfMillisecond);
} else {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
import org.junit.jupiter.api.Test;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;

Expand All @@ -50,8 +51,10 @@ public void testCategoryAndClass() {
public void testGetPrimitiveJavaObject() {
PaimonTimestampLocalTZObjectInspector oi = new PaimonTimestampLocalTZObjectInspector();

LocalDateTime now = LocalDateTime.now().plusNanos(123);
Timestamp input = Timestamp.fromLocalDateTime(now);
long nowMs = System.currentTimeMillis();
LocalDateTime now =
LocalDateTime.ofInstant(Instant.ofEpochMilli(nowMs), ZoneId.systemDefault());
Timestamp input = Timestamp.fromEpochMillis(nowMs);
TimestampTZ expected = new TimestampTZ(now.atZone(ZoneId.systemDefault()));
assertThat(oi.getPrimitiveJavaObject(input)).isEqualTo(expected);

Expand All @@ -62,8 +65,10 @@ public void testGetPrimitiveJavaObject() {
public void testGetPrimitiveWritableObject() {
PaimonTimestampLocalTZObjectInspector oi = new PaimonTimestampLocalTZObjectInspector();

LocalDateTime now = LocalDateTime.now().plusNanos(123);
Timestamp input = Timestamp.fromLocalDateTime(now);
long nowMs = System.currentTimeMillis();
LocalDateTime now =
LocalDateTime.ofInstant(Instant.ofEpochMilli(nowMs), ZoneId.systemDefault());
Timestamp input = Timestamp.fromEpochMillis(nowMs);
TimestampTZ expected = new TimestampTZ(now.atZone(ZoneId.systemDefault()));
assertThat(oi.getPrimitiveWritableObject(input).getTimestampTZ()).isEqualTo(expected);

Expand Down Expand Up @@ -92,8 +97,10 @@ public void testCopyObject() {
public void testConvertObject() {
PaimonTimestampLocalTZObjectInspector oi = new PaimonTimestampLocalTZObjectInspector();

LocalDateTime now = LocalDateTime.now().plusNanos(123);
Timestamp expected = Timestamp.fromLocalDateTime(now);
long nowMs = System.currentTimeMillis();
LocalDateTime now =
LocalDateTime.ofInstant(Instant.ofEpochMilli(nowMs), ZoneId.systemDefault());
Timestamp expected = Timestamp.fromEpochMillis(nowMs);
TimestampTZ input = new TimestampTZ(now.atZone(ZoneId.systemDefault()));
assertThat(oi.convert(input)).isEqualTo(expected);

Expand Down
Loading