diff --git a/src/main/java/org/apache/commons/beanutils2/converters/DateTimeConverter.java b/src/main/java/org/apache/commons/beanutils2/converters/DateTimeConverter.java index 7515b3461..3e7952df8 100644 --- a/src/main/java/org/apache/commons/beanutils2/converters/DateTimeConverter.java +++ b/src/main/java/org/apache/commons/beanutils2/converters/DateTimeConverter.java @@ -200,7 +200,7 @@ protected T convertToType(final Class targetType, final Object value) thr // didn't include the milliseconds. The following code // ensures it works consistently across JDK versions final java.sql.Timestamp timestamp = (java.sql.Timestamp) value; - long timeInMillis = timestamp.getTime() / 1000 * 1000; + long timeInMillis = Math.floorDiv(timestamp.getTime(), 1000) * 1000; timeInMillis += timestamp.getNanos() / 1000000; return toDate(targetType, timeInMillis); } diff --git a/src/test/java/org/apache/commons/beanutils2/converters/DateConverterTest.java b/src/test/java/org/apache/commons/beanutils2/converters/DateConverterTest.java index a3cd6e40c..282f67192 100644 --- a/src/test/java/org/apache/commons/beanutils2/converters/DateConverterTest.java +++ b/src/test/java/org/apache/commons/beanutils2/converters/DateConverterTest.java @@ -17,9 +17,14 @@ package org.apache.commons.beanutils2.converters; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.sql.Timestamp; import java.util.Calendar; import java.util.Date; +import org.junit.jupiter.api.Test; + /** * Test Case for the DateConverter class. */ @@ -66,4 +71,16 @@ protected DateConverter makeConverter(final Date defaultValue) { protected Date toType(final Calendar value) { return value.getTime(); } + + /** + * A pre-epoch {@link Timestamp} carries a non-negative sub-second part in {@code getNanos()}, so decomposing + * {@code getTime()} into whole seconds must floor: integer division truncates toward zero for negative values and + * gains a whole second. + */ + @Test + void testConvertPreEpochSqlTimestamp() { + // 1969-12-31T23:59:59.500Z: getTime() == -500, getNanos() == 500_000_000 + final Timestamp timestamp = new Timestamp(-500L); + assertEquals(-500L, makeConverter().convert(getExpectedType(), timestamp).getTime()); + } }