[java-core] Timestamp.of(java.sql.Timestamp) is one second late for a time less than a second before the epoch
Maintainers usually reply within 1 day
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 78/100
Research direction
Start in sdk-platform-java/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java, at the Timestamp.of(java.sql.Timestamp) method linked in the issue. Compare its seconds calculation with Timestamp.of(Date) and the reproducer values around the epoch. Done means conversion is correct for the negative subsecond cases and agrees with Timestamp.of(Date); the issue does not name a test file.
Written by the indexing model from the issue text.
Description
Issue Details
Timestamp.of(java.sql.Timestamp) returns a time one second late for a java.sql.Timestamp between one second before the epoch and the epoch:
The method takes the whole seconds as getTime() / 1000 and borrows a second only when that quotient is negative. For getTime() in (-1000, 0) the quotient is 0, so no second is borrowed, while getNanos() holds the positive fraction of the second before the epoch. new java.sql.Timestamp(-500) (1969-12-31T23:59:59.500Z) becomes 1970-01-01T00:00:00.500Z. The borrow was added for googleapis/java-core#159, whose example (-1001) has a nonzero quotient, so this range was left out. Math.floorDiv(getTime(), 1000) gives the right seconds for every value, as Timestamp.of(Date) already does through ofTimeMicroseconds.
Found while building an Apache Flink connector on google-cloud-firestore (flink-gcp/flink-connector-gcp).
Environment
- OS Type and Version: macOS 26 (arm64)
- Java Version and JDK Vendor: Eclipse Temurin 17.0.20
Dependencies
- Libraries-Bom: 26.90.0
- google-cloud-core 2.77.0
The affected code is identical in 2.77.0 and on main.
Reproducer
package repro;
import com.google.cloud.Timestamp;
public class SqlTimestampProbe {
public static void main(String[] args) {
for (long millis : new long[] {-1500, -500, -1, 0, 500}) {
java.sql.Timestamp sql = new java.sql.Timestamp(millis);
System.out.println(millis + " ms (" + sql.toInstant() + "): Timestamp.of(sql) = " + Timestamp.of(sql)
+ ", Timestamp.of(Date) = " + Timestamp.of(new java.util.Date(millis)));
}
}
}
Logs and Stack Trace
-1500 ms (1969-12-31T23:59:58.500Z): Timestamp.of(sql) = 1969-12-31T23:59:58.500000000Z, Timestamp.of(Date) = 1969-12-31T23:59:58.500000000Z
-500 ms (1969-12-31T23:59:59.500Z): Timestamp.of(sql) = 1970-01-01T00:00:00.500000000Z, Timestamp.of(Date) = 1969-12-31T23:59:59.500000000Z
-1 ms (1969-12-31T23:59:59.999Z): Timestamp.of(sql) = 1970-01-01T00:00:00.999000000Z, Timestamp.of(Date) = 1969-12-31T23:59:59.999000000Z
0 ms (1970-01-01T00:00:00Z): Timestamp.of(sql) = 1970-01-01T00:00:00Z, Timestamp.of(Date) = 1970-01-01T00:00:00Z
500 ms (1970-01-01T00:00:00.500Z): Timestamp.of(sql) = 1970-01-01T00:00:00.500000000Z, Timestamp.of(Date) = 1970-01-01T00:00:00.500000000Z
Behavior
Deterministic: any java.sql.Timestamp with -1000 < getTime() < 0.
- Dominant language
- Java
- Stars
- 2.1k
- Forks
- 1.2k
- Avg merge
- 2d 14h
- Merged PRs (30d)
- 192
Getting set up
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from googleapis/google-cloud-java
-
[java-firestore] UserDataConverter encodes a pre-epoch Date with negative nanos, so the write is refusedPossibly taken @wu-hui claimed this 23 days ago. Openpriority: p2 type: bug
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
googleapis/google-cloud-java#14635 · 1 assignee ·
Maintainers usually reply within 1 day
-
[java-firestore] UserDataConverter throws IndexOutOfBoundsException on an empty __binary__ valuePossibly taken @wu-hui claimed this 23 days ago. Openpriority: p2 type: bug
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
googleapis/google-cloud-java#14634 · 1 comment · 1 assignee ·
Maintainers usually reply within 1 day
-
[java-firestore] CustomClassMapper.convertBigDecimal calls .abs() on Double, unintentionally flipping negative values to positiveMay be free again @wu-hui claimed this 45 days ago, and no pull request is open. Open
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
googleapis/google-cloud-java#14533 · 1 assignee ·
Maintainers usually reply within 1 day
-
Github CI failing when trying to install xmllintPossibly taken @blakeli0 claimed this 81 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
googleapis/google-cloud-java#14132 · 1 comment ·
Maintainers usually reply within 1 day
-
BigQuery: create() throws NullPointerException on a duplicate job id outside the US multi-region (java-bigquery#3034 not fixed by #3035)Possibly taken @laughingman7743 claimed this 95 days ago. Openpriority: p3 type: bug
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
googleapis/google-cloud-java#14025 ·
Maintainers usually reply within 1 day
All issues in googleapis/google-cloud-java
Similar issues
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
bug:unconfirmed
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
UniversalMediaServer/UniversalMediaServer#6473 ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 82/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
ClickHouse/clickhouse-java#3349 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
StarRocks/starrocks#83246 · 1 comment ·
Maintainers usually reply within 1 day