diff --git a/google-cloud-clients/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java b/google-cloud-clients/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java index 0c2eca786367..17e26d9c9993 100644 --- a/google-cloud-clients/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java +++ b/google-cloud-clients/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java @@ -78,9 +78,12 @@ public static Timestamp ofTimeSecondsAndNanos(long seconds, int nanos) { * @throws IllegalArgumentException if the timestamp is outside the representable range */ public static Timestamp ofTimeMicroseconds(long microseconds) { - long seconds = TimeUnit.MICROSECONDS.toSeconds(microseconds); - int nanos = - (int) TimeUnit.MICROSECONDS.toNanos(microseconds - TimeUnit.SECONDS.toMicros(seconds)); + long seconds = microseconds / 1_000_000; + int nanos = (int)(microseconds % 1_000_000 * 1000); + if (nanos < 0) { + seconds--; + nanos += 1_000_000_000; + } checkArgument( Timestamps.isValid(seconds, nanos), "timestamp out of range: %s, %s", seconds, nanos); return new Timestamp(seconds, nanos); diff --git a/google-cloud-clients/google-cloud-core/src/test/java/com/google/cloud/TimestampTest.java b/google-cloud-clients/google-cloud-core/src/test/java/com/google/cloud/TimestampTest.java index 51d2ecb20f18..c78f54627c77 100644 --- a/google-cloud-clients/google-cloud-core/src/test/java/com/google/cloud/TimestampTest.java +++ b/google-cloud-clients/google-cloud-core/src/test/java/com/google/cloud/TimestampTest.java @@ -39,7 +39,9 @@ public class TimestampTest { private static final long TEST_TIME_MICROSECONDS = 10000100L; private static final long TEST_TIME_MILLISECONDS = TimeUnit.SECONDS.toMillis(1444662894L) + TimeUnit.MICROSECONDS.toMillis(1234); + private static final long TEST_TIME_MILLISECONDS_NEGATIVE = -1000L; private static final Date TEST_DATE = new Date(TEST_TIME_MILLISECONDS); + private static final Date TEST_DATE_PRE_EPOCH = new Date(TEST_TIME_MILLISECONDS_NEGATIVE); @Rule public ExpectedException expectedException = ExpectedException.none(); @@ -80,6 +82,19 @@ public void ofDate() { assertThat(timestamp.getNanos()).isEqualTo(expectedNanos); } + @Test + public void ofDatePreEpoch() { + Timestamp timestamp = Timestamp.of(TEST_DATE_PRE_EPOCH); + long expectedSeconds = TEST_TIME_MILLISECONDS_NEGATIVE / 1_000; + int expectedNanos = (int)(TEST_TIME_MILLISECONDS_NEGATIVE % 1_000 * 1000_000); + if (expectedNanos < 0) { + expectedSeconds--; + expectedNanos += 1_000_000_000; + } + assertThat(timestamp.getSeconds()).isEqualTo(expectedSeconds); + assertThat(timestamp.getNanos()).isEqualTo(expectedNanos); + } + @Test public void toDate() { Timestamp timestamp = Timestamp.ofTimeSecondsAndNanos(TEST_TIME_SECONDS, 1234 * 1000);