Skip to content
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 @@ -126,6 +126,14 @@ private static ByteBuffer timestampToByteBuffer(Timestamp timestamp, int precisi
.putLong(0, timestamp.toMicros());
}

private static Timestamp timestampFromBytes(byte[] bytes, int precision) {
Preconditions.checkArgument(
precision >= 3 && precision <= 6,
"Paimon Iceberg compatibility only support timestamp type with precision from 3 to 6.");
long encoded = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getLong();
return precision == 3 ? Timestamp.fromEpochMillis(encoded) : Timestamp.fromMicros(encoded);
}

private static ByteBuffer timeToByteBuffer(int millisOfDay, int precision) {
Preconditions.checkArgument(
precision >= 0 && precision <= 3,
Expand Down Expand Up @@ -164,17 +172,11 @@ public static Object toPaimonObject(DataType type, byte[] bytes) {
return Decimal.fromUnscaledBytes(
bytes, decimalType.getPrecision(), decimalType.getScale());
case TIMESTAMP_WITHOUT_TIME_ZONE:
return timestampFromBytes(bytes, ((TimestampType) type).getPrecision());
case TIMESTAMP_WITH_LOCAL_TIME_ZONE:
int timestampPrecision = ((TimestampType) type).getPrecision();
long timestampLong =
ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getLong();
Preconditions.checkArgument(
timestampPrecision >= 3 && timestampPrecision <= 6,
"Paimon Iceberg compatibility only support timestamp type with precision from 3 to 6.");
if (timestampPrecision == 3) {
return Timestamp.fromEpochMillis(timestampLong);
}
return Timestamp.fromMicros(timestampLong);
// LocalZonedTimestampType does not extend TimestampType, so it cannot
// share a switch arm with TIMESTAMP_WITHOUT_TIME_ZONE.
return timestampFromBytes(bytes, ((LocalZonedTimestampType) type).getPrecision());
case TIME_WITHOUT_TIME_ZONE:
int timePrecision = ((TimeType) type).getPrecision();
Preconditions.checkArgument(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,4 +125,20 @@ void testToPaimonObjectTimestampInvalid(int precision, long serializedMicros) {
private static Stream<Arguments> provideInvalidTimestampCases() {
return Stream.of(Arguments.of(0, 1698686153L), Arguments.of(9, 1698686153123456789L));
}

@ParameterizedTest
@MethodSource("provideTimestampToPaimonCases")
@DisplayName("toPaimonObject decodes TIMESTAMP_WITH_LOCAL_TIME_ZONE without ClassCastException")
void testToPaimonObjectForTimestampWithLocalTimeZone(
int precision, long serializedMicros, String expectedTs) {
byte[] bytes = new byte[8];
ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).putLong(serializedMicros);

Timestamp actual =
(Timestamp)
IcebergConversions.toPaimonObject(
DataTypes.TIMESTAMP_WITH_LOCAL_TIME_ZONE(precision), bytes);

assertThat(actual.toString()).isEqualTo(expectedTs);
}
}