Skip to content

Commit 6b7769a

Browse files
committed
Fix Internal to Generic conversion of TIMESTAMP_NANO
1 parent 15485f5 commit 6b7769a

2 files changed

Lines changed: 24 additions & 0 deletions

File tree

core/src/main/java/org/apache/iceberg/data/GenericDataUtil.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ public static Object internalToGeneric(Type type, Object value) {
5151
} else {
5252
return DateTimeUtil.timestampFromMicros((Long) value);
5353
}
54+
case TIMESTAMP_NANO:
55+
if (((Types.TimestampNanoType) type).shouldAdjustToUTC()) {
56+
return DateTimeUtil.timestamptzFromNanos((Long) value);
57+
} else {
58+
return DateTimeUtil.timestampFromNanos((Long) value);
59+
}
5460
case FIXED:
5561
return ByteBuffers.toByteArray((ByteBuffer) value);
5662
}

core/src/test/java/org/apache/iceberg/data/DataTestBase.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import static org.apache.iceberg.types.Types.NestedField.optional;
2222
import static org.apache.iceberg.types.Types.NestedField.required;
23+
import static org.assertj.core.api.Assertions.assertThat;
2324
import static org.assertj.core.api.Assertions.assertThatThrownBy;
2425
import static org.assertj.core.api.Assumptions.assumeThat;
2526

@@ -28,6 +29,8 @@
2829
import java.math.BigDecimal;
2930
import java.nio.ByteBuffer;
3031
import java.nio.file.Path;
32+
import java.time.LocalDateTime;
33+
import java.time.OffsetDateTime;
3134
import java.util.List;
3235
import java.util.Map;
3336
import java.util.UUID;
@@ -595,6 +598,7 @@ public void testPrimitiveTypeDefaultValues(Type.PrimitiveType type, Literal<?> d
595598
}
596599

597600
@Test
601+
@SuppressWarnings("checkstyle:AssertThatThrownByWithMessageCheck")
598602
public void testWriteNullValueForRequiredType() throws Exception {
599603
Schema schema =
600604
new Schema(
@@ -645,4 +649,18 @@ public void testRowLineage() throws Exception {
645649
record.copy(Map.of("id", 4L, "data", "d", "_row_id", 1_001L)),
646650
record.copy(Map.of("id", 5L, "data", "e"))));
647651
}
652+
653+
@Test
654+
public void testTimestampNanoMaterializedAsJavaTime() {
655+
assumeThat(supportsTimestampNanos()).as("timestamp_ns is not yet implemented").isTrue();
656+
657+
long epochNanos = DateTimeUtil.isoTimestampToNanos("2025-01-15T11:25:20.111456789");
658+
assertThat(GenericDataUtil.internalToGeneric(Types.TimestampNanoType.withZone(), epochNanos))
659+
.as("TIMESTAMP_NANO with zone must be materialized as OffsetDateTime")
660+
.isInstanceOf(OffsetDateTime.class);
661+
662+
assertThat(GenericDataUtil.internalToGeneric(Types.TimestampNanoType.withoutZone(), epochNanos))
663+
.as("TIMESTAMP_NANO must be materialized as LocalDateTime")
664+
.isInstanceOf(LocalDateTime.class);
665+
}
648666
}

0 commit comments

Comments
 (0)