This is an automated email from the ASF dual-hosted git repository.
nandorKollar pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/avro.git
The following commit(s) were added to refs/heads/main by this push:
new 912ab25169 AVRO-4269: Fix timestamp-nanos conversion before epoch
(#3813)
912ab25169 is described below
commit 912ab25169ab829d5c523fd231b5abb286c4dbe1
Author: Emanuele Russo <[email protected]>
AuthorDate: Thu Jun 18 23:56:11 2026 +0200
AVRO-4269: Fix timestamp-nanos conversion before epoch (#3813)
---
.../java/org/apache/avro/data/TimeConversions.java | 2 +-
.../org/apache/avro/data/TestTimeConversions.java | 19 +++++++++++++++++++
2 files changed, 20 insertions(+), 1 deletion(-)
diff --git
a/lang/java/avro/src/main/java/org/apache/avro/data/TimeConversions.java
b/lang/java/avro/src/main/java/org/apache/avro/data/TimeConversions.java
index e63ebaae6e..0e24e0aec2 100644
--- a/lang/java/avro/src/main/java/org/apache/avro/data/TimeConversions.java
+++ b/lang/java/avro/src/main/java/org/apache/avro/data/TimeConversions.java
@@ -235,7 +235,7 @@ public class TimeConversions {
if (seconds < 0 && nanos > 0) {
long micros = Math.multiplyExact(seconds + 1, 1_000_000_000L);
- long adjustment = nanos - 1_000_000;
+ long adjustment = nanos - 1_000_000_000L;
return Math.addExact(micros, adjustment);
} else {
diff --git
a/lang/java/avro/src/test/java/org/apache/avro/data/TestTimeConversions.java
b/lang/java/avro/src/test/java/org/apache/avro/data/TestTimeConversions.java
index 089915803a..07df0934e4 100644
--- a/lang/java/avro/src/test/java/org/apache/avro/data/TestTimeConversions.java
+++ b/lang/java/avro/src/test/java/org/apache/avro/data/TestTimeConversions.java
@@ -33,6 +33,7 @@ import
org.apache.avro.data.TimeConversions.TimeMicrosConversion;
import org.apache.avro.data.TimeConversions.TimeMillisConversion;
import org.apache.avro.data.TimeConversions.TimestampMicrosConversion;
import org.apache.avro.data.TimeConversions.TimestampMillisConversion;
+import org.apache.avro.data.TimeConversions.TimestampNanosConversion;
import org.apache.avro.reflect.ReflectData;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
@@ -44,6 +45,7 @@ public class TestTimeConversions {
public static Schema TIME_MICROS_SCHEMA;
public static Schema TIMESTAMP_MILLIS_SCHEMA;
public static Schema TIMESTAMP_MICROS_SCHEMA;
+ public static Schema TIMESTAMP_NANOS_SCHEMA;
@BeforeAll
public static void createSchemas() {
@@ -54,6 +56,8 @@ public class TestTimeConversions {
.addToSchema(Schema.create(Schema.Type.LONG));
TestTimeConversions.TIMESTAMP_MICROS_SCHEMA =
LogicalTypes.timestampMicros()
.addToSchema(Schema.create(Schema.Type.LONG));
+ TestTimeConversions.TIMESTAMP_NANOS_SCHEMA = LogicalTypes.timestampNanos()
+ .addToSchema(Schema.create(Schema.Type.LONG));
}
@Test
@@ -191,6 +195,21 @@ public class TestTimeConversions {
"Pre 1970 date should be correct");
}
+ @Test
+ void timestampNanosConversionBeforeEpochWithPositiveNanos() {
+ TimestampNanosConversion conversion = new TimestampNanosConversion();
+
+ // < Epoch
+ long Dec_31_1969_23_59_59_999_999_999_instant = -1L;
+ Instant Dec_31_1969_23_59_59_999_999_999 = ZonedDateTime.of(1969, 12, 31,
23, 59, 59, 999_999_999, ZoneOffset.UTC)
+ .toInstant();
+
+ assertEquals(Dec_31_1969_23_59_59_999_999_999,
conversion.fromLong(Dec_31_1969_23_59_59_999_999_999_instant,
+ TIMESTAMP_NANOS_SCHEMA, LogicalTypes.timestampNanos()), "Pre 1970
nanos date should be correct");
+ assertEquals(Dec_31_1969_23_59_59_999_999_999_instant, (long)
conversion.toLong(Dec_31_1969_23_59_59_999_999_999,
+ TIMESTAMP_NANOS_SCHEMA, LogicalTypes.timestampNanos()), "Pre 1970
nanos date should be correct");
+ }
+
@Test
void dynamicSchemaWithDateConversion() throws ClassNotFoundException {
Schema schema = getReflectedSchemaByName("java.time.LocalDate", new
TimeConversions.DateConversion());