From 52e207214e6ced1b9c58b59f4cd159b58583413a Mon Sep 17 00:00:00 2001 From: diegomarquezp Date: Thu, 31 Oct 2024 19:13:16 +0000 Subject: [PATCH 01/16] feat: introduce `java.time` to java-core --- .../java/com/google/cloud/RetryOption.java | 29 ++++++++++++++----- .../java/com/google/cloud/ServiceOptions.java | 12 ++++---- .../main/java/com/google/cloud/Timestamp.java | 14 ++++----- .../cloud/testing/BaseEmulatorHelper.java | 2 +- .../cloud/testing/BaseEmulatorHelperTest.java | 2 +- 5 files changed, 37 insertions(+), 22 deletions(-) diff --git a/java-core/google-cloud-core/src/main/java/com/google/cloud/RetryOption.java b/java-core/google-cloud-core/src/main/java/com/google/cloud/RetryOption.java index a1069b48a2..262e2ae9e0 100644 --- a/java-core/google-cloud-core/src/main/java/com/google/cloud/RetryOption.java +++ b/java-core/google-cloud-core/src/main/java/com/google/cloud/RetryOption.java @@ -16,12 +16,12 @@ package com.google.cloud; +import static com.google.api.gax.util.TimeConversionUtils.toJavaTimeDuration; import static com.google.common.base.Preconditions.checkNotNull; import com.google.api.core.BetaApi; import com.google.api.gax.retrying.RetrySettings; import java.io.Serializable; -import org.threeten.bp.Duration; /** * This class represents an options wrapper around the {@link RetrySettings} class and is an @@ -52,12 +52,22 @@ private RetryOption(OptionType type, Object value) { } /** See {@link RetrySettings#getTotalTimeout()}. */ - public static RetryOption totalTimeout(Duration totalTimeout) { + public static RetryOption totalTimeout(org.threeten.bp.Duration totalTimeout) { + return totalTimeoutDuration(toJavaTimeDuration(totalTimeout)); + } + + /** See {@link RetrySettings#getTotalTimeout()}. */ + public static RetryOption totalTimeoutDuration(java.time.Duration totalTimeout) { return new RetryOption(OptionType.TOTAL_TIMEOUT, totalTimeout); } /** See {@link RetrySettings#getInitialRetryDelay()}. */ - public static RetryOption initialRetryDelay(Duration initialRetryDelay) { + public static RetryOption initialRetryDelay(org.threeten.bp.Duration initialRetryDelay) { + return initialRetryDelayDuration(toJavaTimeDuration(initialRetryDelay)); + } + + /** See {@link RetrySettings#getInitialRetryDelay()}. */ + public static RetryOption initialRetryDelayDuration(java.time.Duration initialRetryDelay) { return new RetryOption(OptionType.INITIAL_RETRY_DELAY, initialRetryDelay); } @@ -67,7 +77,12 @@ public static RetryOption retryDelayMultiplier(double retryDelayMultiplier) { } /** See {@link RetrySettings#getMaxRetryDelay()}. */ - public static RetryOption maxRetryDelay(Duration maxRetryDelay) { + public static RetryOption maxRetryDelay(org.threeten.bp.Duration maxRetryDelay) { + return maxRetryDelayDuration(toJavaTimeDuration(maxRetryDelay)); + } + + /** See {@link RetrySettings#getMaxRetryDelay()}. */ + public static RetryOption maxRetryDelayDuration(java.time.Duration maxRetryDelay) { return new RetryOption(OptionType.MAX_RETRY_DELAY, maxRetryDelay); } @@ -124,16 +139,16 @@ public static RetrySettings mergeToSettings(RetrySettings settings, RetryOption. for (RetryOption option : options) { switch (option.type) { case TOTAL_TIMEOUT: - builder.setTotalTimeout((Duration) option.value); + builder.setTotalTimeoutDuration((java.time.Duration) option.value); break; case INITIAL_RETRY_DELAY: - builder.setInitialRetryDelay((Duration) option.value); + builder.setInitialRetryDelayDuration((java.time.Duration) option.value); break; case RETRY_DELAY_MULTIPLIER: builder.setRetryDelayMultiplier((Double) option.value); break; case MAX_RETRY_DELAY: - builder.setMaxRetryDelay((Duration) option.value); + builder.setMaxRetryDelayDuration((java.time.Duration) option.value); break; case MAX_ATTEMPTS: builder.setMaxAttempts((Integer) option.value); diff --git a/java-core/google-cloud-core/src/main/java/com/google/cloud/ServiceOptions.java b/java-core/google-cloud-core/src/main/java/com/google/cloud/ServiceOptions.java index 985fac4804..92aaa9d6a9 100644 --- a/java-core/google-cloud-core/src/main/java/com/google/cloud/ServiceOptions.java +++ b/java-core/google-cloud-core/src/main/java/com/google/cloud/ServiceOptions.java @@ -63,6 +63,7 @@ import java.io.Serializable; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.time.Duration; import java.util.Locale; import java.util.Map; import java.util.Objects; @@ -70,7 +71,6 @@ import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.threeten.bp.Duration; /** * Abstract class representing service options. @@ -787,13 +787,13 @@ public static RetrySettings getNoRetrySettings() { private static RetrySettings.Builder getDefaultRetrySettingsBuilder() { return RetrySettings.newBuilder() .setMaxAttempts(6) - .setInitialRetryDelay(Duration.ofMillis(1000L)) - .setMaxRetryDelay(Duration.ofMillis(32_000L)) + .setInitialRetryDelayDuration(Duration.ofMillis(1000L)) + .setMaxRetryDelayDuration(Duration.ofMillis(32_000L)) .setRetryDelayMultiplier(2.0) - .setTotalTimeout(Duration.ofMillis(50_000L)) - .setInitialRpcTimeout(Duration.ofMillis(50_000L)) + .setTotalTimeoutDuration(Duration.ofMillis(50_000L)) + .setInitialRpcTimeoutDuration(Duration.ofMillis(50_000L)) .setRpcTimeoutMultiplier(1.0) - .setMaxRpcTimeout(Duration.ofMillis(50_000L)); + .setMaxRpcTimeoutDuration(Duration.ofMillis(50_000L)); } protected abstract Set getScopes(); diff --git a/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java b/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java index e0308c3836..79c9ff5289 100644 --- a/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java +++ b/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java @@ -20,16 +20,16 @@ import com.google.protobuf.util.Timestamps; import java.io.Serializable; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.format.DateTimeParseException; +import java.time.temporal.TemporalAccessor; import java.util.Date; import java.util.Objects; import java.util.concurrent.TimeUnit; -import org.threeten.bp.Instant; -import org.threeten.bp.LocalDateTime; -import org.threeten.bp.ZoneOffset; -import org.threeten.bp.format.DateTimeFormatter; -import org.threeten.bp.format.DateTimeFormatterBuilder; -import org.threeten.bp.format.DateTimeParseException; -import org.threeten.bp.temporal.TemporalAccessor; /** * Represents a timestamp with nanosecond precision. Timestamps cover the range [0001-01-01, diff --git a/java-core/google-cloud-core/src/main/java/com/google/cloud/testing/BaseEmulatorHelper.java b/java-core/google-cloud-core/src/main/java/com/google/cloud/testing/BaseEmulatorHelper.java index 9679c6299c..0c002d0f01 100644 --- a/java-core/google-cloud-core/src/main/java/com/google/cloud/testing/BaseEmulatorHelper.java +++ b/java-core/google-cloud-core/src/main/java/com/google/cloud/testing/BaseEmulatorHelper.java @@ -45,6 +45,7 @@ import java.nio.file.Path; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.time.Duration; import java.util.Arrays; import java.util.List; import java.util.Locale; @@ -56,7 +57,6 @@ import java.util.logging.Logger; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; -import org.threeten.bp.Duration; /** Utility class to start and stop a local service which is used by unit testing. */ @InternalApi diff --git a/java-core/google-cloud-core/src/test/java/com/google/cloud/testing/BaseEmulatorHelperTest.java b/java-core/google-cloud-core/src/test/java/com/google/cloud/testing/BaseEmulatorHelperTest.java index 79b58a83c9..b1772e395d 100644 --- a/java-core/google-cloud-core/src/test/java/com/google/cloud/testing/BaseEmulatorHelperTest.java +++ b/java-core/google-cloud-core/src/test/java/com/google/cloud/testing/BaseEmulatorHelperTest.java @@ -28,12 +28,12 @@ import java.net.URL; import java.net.URLConnection; import java.net.URLStreamHandler; +import java.time.Duration; import java.util.List; import java.util.concurrent.TimeoutException; import java.util.logging.Logger; import org.easymock.EasyMock; import org.junit.jupiter.api.Test; -import org.threeten.bp.Duration; class BaseEmulatorHelperTest { From bd04ceaaa9c2b1826d10a0c36d8f037adf067107 Mon Sep 17 00:00:00 2001 From: diegomarquezp Date: Thu, 31 Oct 2024 19:17:22 +0000 Subject: [PATCH 02/16] fix comments and add obsolete api annotation --- .../main/java/com/google/cloud/RetryOption.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/java-core/google-cloud-core/src/main/java/com/google/cloud/RetryOption.java b/java-core/google-cloud-core/src/main/java/com/google/cloud/RetryOption.java index 262e2ae9e0..f69b0d1c76 100644 --- a/java-core/google-cloud-core/src/main/java/com/google/cloud/RetryOption.java +++ b/java-core/google-cloud-core/src/main/java/com/google/cloud/RetryOption.java @@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.api.core.BetaApi; +import com.google.api.core.ObsoleteApi; import com.google.api.gax.retrying.RetrySettings; import java.io.Serializable; @@ -51,22 +52,24 @@ private RetryOption(OptionType type, Object value) { this.value = checkNotNull(value); } - /** See {@link RetrySettings#getTotalTimeout()}. */ + /** This method is obsolete. Use {@link #totalTimeoutDuration(java.time.Duration)} instead */ + @ObsoleteApi("Use totalTimeouDuration() instead") public static RetryOption totalTimeout(org.threeten.bp.Duration totalTimeout) { return totalTimeoutDuration(toJavaTimeDuration(totalTimeout)); } - /** See {@link RetrySettings#getTotalTimeout()}. */ + /** See {@link RetrySettings#getTotalTimeoutDuration()}. */ public static RetryOption totalTimeoutDuration(java.time.Duration totalTimeout) { return new RetryOption(OptionType.TOTAL_TIMEOUT, totalTimeout); } - /** See {@link RetrySettings#getInitialRetryDelay()}. */ + /** This method is obsolete. Use {@link #initialRetryDelayDuration(java.time.Duration)} instead */ + @ObsoleteApi("Use initialRetryDelayDuration() instead") public static RetryOption initialRetryDelay(org.threeten.bp.Duration initialRetryDelay) { return initialRetryDelayDuration(toJavaTimeDuration(initialRetryDelay)); } - /** See {@link RetrySettings#getInitialRetryDelay()}. */ + /** See {@link RetrySettings#getInitialRetryDelayDuration()}. */ public static RetryOption initialRetryDelayDuration(java.time.Duration initialRetryDelay) { return new RetryOption(OptionType.INITIAL_RETRY_DELAY, initialRetryDelay); } @@ -76,12 +79,13 @@ public static RetryOption retryDelayMultiplier(double retryDelayMultiplier) { return new RetryOption(OptionType.RETRY_DELAY_MULTIPLIER, retryDelayMultiplier); } - /** See {@link RetrySettings#getMaxRetryDelay()}. */ + /** This method is obsolete. Use {@link #maxRetryDelayDuration(java.time.Duration)} instead */ + @ObsoleteApi("Use maxRetryDelayDuration() instead") public static RetryOption maxRetryDelay(org.threeten.bp.Duration maxRetryDelay) { return maxRetryDelayDuration(toJavaTimeDuration(maxRetryDelay)); } - /** See {@link RetrySettings#getMaxRetryDelay()}. */ + /** See {@link RetrySettings#getMaxRetryDelayDuration()}. */ public static RetryOption maxRetryDelayDuration(java.time.Duration maxRetryDelay) { return new RetryOption(OptionType.MAX_RETRY_DELAY, maxRetryDelay); } From dc11006ed02f46f8b6d0ee8229fe261063fb4134 Mon Sep 17 00:00:00 2001 From: diegomarquezp Date: Thu, 31 Oct 2024 19:30:32 +0000 Subject: [PATCH 03/16] add java.time to tests --- .../com/google/cloud/RetryOptionTest.java | 45 +++++++++++++------ .../com/google/cloud/SerializationTest.java | 4 +- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/java-core/google-cloud-core/src/test/java/com/google/cloud/RetryOptionTest.java b/java-core/google-cloud-core/src/test/java/com/google/cloud/RetryOptionTest.java index a458d31f67..192cc21f5f 100644 --- a/java-core/google-cloud-core/src/test/java/com/google/cloud/RetryOptionTest.java +++ b/java-core/google-cloud-core/src/test/java/com/google/cloud/RetryOptionTest.java @@ -20,27 +20,30 @@ import static org.junit.jupiter.api.Assertions.assertNotEquals; import com.google.api.gax.retrying.RetrySettings; +import java.time.Duration; import org.junit.jupiter.api.Test; -import org.threeten.bp.Duration; class RetryOptionTest { + private static final long TOTAL_TIMEOUT_MILLIS = 420l; + private static final long INITIAL_RETRY_DELAY_MILLIS = 42l; + private static final long MAX_RETRY_DELAY_MILLIS = 100l; private static final RetryOption TOTAL_TIMEOUT = - RetryOption.totalTimeout(Duration.ofMillis(420L)); + RetryOption.totalTimeoutDuration(Duration.ofMillis(TOTAL_TIMEOUT_MILLIS)); private static final RetryOption INITIAL_RETRY_DELAY = - RetryOption.initialRetryDelay(Duration.ofMillis(42L)); + RetryOption.initialRetryDelayDuration(Duration.ofMillis(INITIAL_RETRY_DELAY_MILLIS)); private static final RetryOption RETRY_DELAY_MULTIPLIER = RetryOption.retryDelayMultiplier(1.5); private static final RetryOption MAX_RETRY_DELAY = - RetryOption.maxRetryDelay(Duration.ofMillis(100)); + RetryOption.maxRetryDelayDuration(Duration.ofMillis(MAX_RETRY_DELAY_MILLIS)); private static final RetryOption MAX_ATTEMPTS = RetryOption.maxAttempts(100); private static final RetryOption JITTERED = RetryOption.jittered(false); private static final RetrySettings retrySettings = RetrySettings.newBuilder() - .setTotalTimeout(Duration.ofMillis(420L)) - .setInitialRetryDelay(Duration.ofMillis(42L)) + .setTotalTimeoutDuration(Duration.ofMillis(420L)) + .setInitialRetryDelayDuration(Duration.ofMillis(42L)) .setRetryDelayMultiplier(1.5) - .setMaxRetryDelay(Duration.ofMillis(100)) + .setMaxRetryDelayDuration(Duration.ofMillis(100)) .setMaxAttempts(100) .setJittered(false) .build(); @@ -61,10 +64,10 @@ void testEqualsAndHashCode() { assertNotEquals(MAX_ATTEMPTS, MAX_RETRY_DELAY); assertNotEquals(JITTERED, MAX_ATTEMPTS); - RetryOption totalTimeout = RetryOption.totalTimeout(Duration.ofMillis(420L)); - RetryOption initialRetryDelay = RetryOption.initialRetryDelay(Duration.ofMillis(42L)); + RetryOption totalTimeout = RetryOption.totalTimeoutDuration(Duration.ofMillis(420L)); + RetryOption initialRetryDelay = RetryOption.initialRetryDelayDuration(Duration.ofMillis(42L)); RetryOption retryDelayMultiplier = RetryOption.retryDelayMultiplier(1.5); - RetryOption maxRetryDelay = RetryOption.maxRetryDelay(Duration.ofMillis(100)); + RetryOption maxRetryDelay = RetryOption.maxRetryDelayDuration(Duration.ofMillis(100)); RetryOption maxAttempts = RetryOption.maxAttempts(100); RetryOption jittered = RetryOption.jittered(false); @@ -101,17 +104,17 @@ void testMergeToSettings() { assertEquals(retrySettings, mergedRetrySettings); defRetrySettings = - defRetrySettings.toBuilder().setTotalTimeout(Duration.ofMillis(420L)).build(); + defRetrySettings.toBuilder().setTotalTimeoutDuration(Duration.ofMillis(420L)).build(); mergedRetrySettings = RetryOption.mergeToSettings(defRetrySettings, TOTAL_TIMEOUT); assertEquals(defRetrySettings, mergedRetrySettings); defRetrySettings = - defRetrySettings.toBuilder().setMaxRetryDelay(Duration.ofMillis(100)).build(); + defRetrySettings.toBuilder().setMaxRetryDelayDuration(Duration.ofMillis(100)).build(); mergedRetrySettings = RetryOption.mergeToSettings(defRetrySettings, MAX_RETRY_DELAY); assertEquals(defRetrySettings, mergedRetrySettings); defRetrySettings = - defRetrySettings.toBuilder().setInitialRetryDelay(Duration.ofMillis(42L)).build(); + defRetrySettings.toBuilder().setInitialRetryDelayDuration(Duration.ofMillis(42L)).build(); mergedRetrySettings = RetryOption.mergeToSettings(defRetrySettings, INITIAL_RETRY_DELAY); assertEquals(defRetrySettings, mergedRetrySettings); @@ -127,4 +130,20 @@ void testMergeToSettings() { mergedRetrySettings = RetryOption.mergeToSettings(defRetrySettings, JITTERED); assertEquals(defRetrySettings, mergedRetrySettings); } + + @Test + public void threetenMethods_producesEquivalentJavaTimeRetryOptions() { + + final RetryOption totalTimeoutThreeten = + RetryOption.totalTimeout(org.threeten.bp.Duration.ofMillis(TOTAL_TIMEOUT_MILLIS)); + final RetryOption initialRetryDelayThreeten = + RetryOption.initialRetryDelay( + org.threeten.bp.Duration.ofMillis(INITIAL_RETRY_DELAY_MILLIS)); + final RetryOption maxRetryDelayThreeten = + RetryOption.maxRetryDelay(org.threeten.bp.Duration.ofMillis(MAX_RETRY_DELAY_MILLIS)); + + assertEquals(TOTAL_TIMEOUT, totalTimeoutThreeten); + assertEquals(INITIAL_RETRY_DELAY, initialRetryDelayThreeten); + assertEquals(MAX_RETRY_DELAY, maxRetryDelayThreeten); + } } diff --git a/java-core/google-cloud-core/src/test/java/com/google/cloud/SerializationTest.java b/java-core/google-cloud-core/src/test/java/com/google/cloud/SerializationTest.java index 6c35c665b5..f591578f11 100644 --- a/java-core/google-cloud-core/src/test/java/com/google/cloud/SerializationTest.java +++ b/java-core/google-cloud-core/src/test/java/com/google/cloud/SerializationTest.java @@ -23,7 +23,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import java.io.Serializable; -import org.threeten.bp.Duration; +import java.time.Duration; public class SerializationTest extends BaseSerializationTest { @@ -37,7 +37,7 @@ public class SerializationTest extends BaseSerializationTest { private static final Role SOME_ROLE = Role.viewer(); private static final Policy SOME_IAM_POLICY = Policy.newBuilder().build(); private static final RetryOption CHECKING_PERIOD = - RetryOption.initialRetryDelay(Duration.ofSeconds(42)); + RetryOption.initialRetryDelayDuration(Duration.ofSeconds(42)); private static final LabelDescriptor LABEL_DESCRIPTOR = new LabelDescriptor("project_id", ValueType.STRING, "The project id"); private static final MonitoredResourceDescriptor MONITORED_RESOURCE_DESCRIPTOR = From bb0d155984b3a6032b4eb121ef4e555c2ba80f54 Mon Sep 17 00:00:00 2001 From: diegomarquezp Date: Thu, 31 Oct 2024 20:11:49 +0000 Subject: [PATCH 04/16] ignore threeten changes --- java-core/google-cloud-core/clirr-ignored-differences.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/java-core/google-cloud-core/clirr-ignored-differences.xml b/java-core/google-cloud-core/clirr-ignored-differences.xml index 0f7f80a7b4..730473d539 100644 --- a/java-core/google-cloud-core/clirr-ignored-differences.xml +++ b/java-core/google-cloud-core/clirr-ignored-differences.xml @@ -12,4 +12,12 @@ com/google/cloud/ReadChannel long limit() + + + 7005 + com/google/cloud/testing/* + * *(org.threeten.bp.Duration) + * + From 34bb09b9b7f3d821ddc9b7472afbe6b477b7d985 Mon Sep 17 00:00:00 2001 From: diegomarquezp Date: Fri, 1 Nov 2024 19:08:19 +0000 Subject: [PATCH 05/16] introduce `java.time` in BaseEmulatorHelper --- .../clirr-ignored-differences.xml | 9 +-- .../cloud/testing/BaseEmulatorHelper.java | 67 ++++++++++++++++--- .../cloud/testing/BaseEmulatorHelperTest.java | 21 ++++-- 3 files changed, 75 insertions(+), 22 deletions(-) diff --git a/java-core/google-cloud-core/clirr-ignored-differences.xml b/java-core/google-cloud-core/clirr-ignored-differences.xml index 730473d539..43b549273f 100644 --- a/java-core/google-cloud-core/clirr-ignored-differences.xml +++ b/java-core/google-cloud-core/clirr-ignored-differences.xml @@ -12,12 +12,9 @@ com/google/cloud/ReadChannel long limit() - - 7005 - com/google/cloud/testing/* - * *(org.threeten.bp.Duration) - * + 7012 + com/google/cloud/testing/BaseEmulatorHelper$EmulatorRunner + int waitForDuration(java.time.Duration) diff --git a/java-core/google-cloud-core/src/main/java/com/google/cloud/testing/BaseEmulatorHelper.java b/java-core/google-cloud-core/src/main/java/com/google/cloud/testing/BaseEmulatorHelper.java index 0c002d0f01..b99b418bf4 100644 --- a/java-core/google-cloud-core/src/main/java/com/google/cloud/testing/BaseEmulatorHelper.java +++ b/java-core/google-cloud-core/src/main/java/com/google/cloud/testing/BaseEmulatorHelper.java @@ -16,8 +16,12 @@ package com.google.cloud.testing; +import static com.google.api.gax.util.TimeConversionUtils.toJavaTimeDuration; +import static com.google.api.gax.util.TimeConversionUtils.toThreetenDuration; + import com.google.api.core.CurrentMillisClock; import com.google.api.core.InternalApi; +import com.google.api.core.ObsoleteApi; import com.google.cloud.ExceptionHandler; import com.google.cloud.RetryHelper; import com.google.cloud.ServiceOptions; @@ -45,7 +49,6 @@ import java.nio.file.Path; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.time.Duration; import java.util.Arrays; import java.util.List; import java.util.Locale; @@ -112,14 +115,21 @@ protected final void startProcess(String blockUntilOutput) } } + /** This method is obsolete. Use {@link #waitForProcessDuration(java.time.Duration)} instead */ + @ObsoleteApi("Use waitForProcessDuration() instead") + protected final int waitForProcess(org.threeten.bp.Duration timeout) + throws IOException, InterruptedException, TimeoutException { + return waitForProcessDuration(toJavaTimeDuration(timeout)); + } + /** * Waits for the local service's subprocess to terminate, and stop any possible thread listening * for its output. */ - protected final int waitForProcess(Duration timeout) + protected final int waitForProcessDuration(java.time.Duration timeout) throws IOException, InterruptedException, TimeoutException { if (activeRunner != null) { - int exitCode = activeRunner.waitFor(timeout); + int exitCode = activeRunner.waitForDuration(timeout); activeRunner = null; return exitCode; } @@ -130,7 +140,14 @@ protected final int waitForProcess(Duration timeout) return 0; } - private static int waitForProcess(final Process process, Duration timeout) + /** This method is obsolete. Use {@link #waitForProcessDuration(java.time.Duration)} instead */ + @ObsoleteApi("Use waitForProcessDuration() instead") + private static int waitForProcess(final Process process, org.threeten.bp.Duration timeout) + throws InterruptedException, TimeoutException { + return waitForProcessDuration(process, toJavaTimeDuration(timeout)); + } + + private static int waitForProcessDuration(final Process process, java.time.Duration timeout) throws InterruptedException, TimeoutException { if (process == null) { return 0; @@ -180,10 +197,17 @@ public String getProjectId() { /** Starts the local emulator. */ public abstract void start() throws IOException, InterruptedException; - /** Stops the local emulator. */ - public abstract void stop(Duration timeout) + /** This method is obsolete. Use {@link #stopDuration(java.time.Duration)} instead */ + @ObsoleteApi("Use stopDuration() instead") + public abstract void stop(org.threeten.bp.Duration timeout) throws IOException, InterruptedException, TimeoutException; + /** Stops the local emulator. */ + public void stopDuration(java.time.Duration timeout) + throws IOException, InterruptedException, TimeoutException { + stop(toThreetenDuration(timeout)); + } + /** Resets the internal state of the emulator. */ public abstract void reset() throws IOException; @@ -226,8 +250,15 @@ protected interface EmulatorRunner { /** Starts the emulator associated to this runner. */ void start() throws IOException; + /** This method is obsolete. Use {@link #waitForDuration(java.time.Duration)} instead */ + @ObsoleteApi("Use waitForDuration() instead") + int waitFor(org.threeten.bp.Duration timeout) throws InterruptedException, TimeoutException; + /** Wait for the emulator associated to this runner to terminate, returning the exit status. */ - int waitFor(Duration timeout) throws InterruptedException, TimeoutException; + default int waitForDuration(java.time.Duration timeout) + throws InterruptedException, TimeoutException { + return waitFor(toThreetenDuration(timeout)); + } /** Returns the process associated to the emulator, if any. */ Process getProcess(); @@ -263,12 +294,20 @@ public void start() throws IOException { log.fine("Starting emulator via Google Cloud SDK"); process = CommandWrapper.create().setCommand(commandText).setRedirectErrorStream().start(); } - + /** This method is obsolete. Use {@link #waitForDuration(java.time.Duration)} instead */ + @ObsoleteApi("Use waitForDuration() instead") @Override - public int waitFor(Duration timeout) throws InterruptedException, TimeoutException { + public int waitFor(org.threeten.bp.Duration timeout) + throws InterruptedException, TimeoutException { return waitForProcess(process, timeout); } + @Override + public int waitForDuration(java.time.Duration timeout) + throws InterruptedException, TimeoutException { + return waitForProcessDuration(process, timeout); + } + @Override public Process getProcess() { return process; @@ -374,11 +413,19 @@ public Path call() throws IOException { .start(); } + /** This method is obsolete. Use {@link #waitForDuration(java.time.Duration)} instead */ + @ObsoleteApi("Use waitForDuration() instead") @Override - public int waitFor(Duration timeout) throws InterruptedException, TimeoutException { + public int waitFor(org.threeten.bp.Duration timeout) + throws InterruptedException, TimeoutException { return waitForProcess(process, timeout); } + public int waitForDuration(java.time.Duration timeout) + throws InterruptedException, TimeoutException { + return waitForProcessDuration(process, timeout); + } + @Override public Process getProcess() { return process; diff --git a/java-core/google-cloud-core/src/test/java/com/google/cloud/testing/BaseEmulatorHelperTest.java b/java-core/google-cloud-core/src/test/java/com/google/cloud/testing/BaseEmulatorHelperTest.java index b1772e395d..beb6e68b85 100644 --- a/java-core/google-cloud-core/src/test/java/com/google/cloud/testing/BaseEmulatorHelperTest.java +++ b/java-core/google-cloud-core/src/test/java/com/google/cloud/testing/BaseEmulatorHelperTest.java @@ -16,6 +16,8 @@ package com.google.cloud.testing; +import static com.google.api.gax.util.TimeConversionUtils.toJavaTimeDuration; + import com.google.api.client.util.Charsets; import com.google.cloud.ServiceOptions; import com.google.cloud.testing.BaseEmulatorHelper.EmulatorRunner; @@ -71,8 +73,15 @@ public void start() throws IOException, InterruptedException { } @Override - public void stop(Duration timeout) throws IOException, InterruptedException, TimeoutException { - waitForProcess(timeout); + public void stop(org.threeten.bp.Duration timeout) + throws IOException, InterruptedException, TimeoutException { + stopDuration(toJavaTimeDuration(timeout)); + } + + @Override + public void stopDuration(Duration timeout) + throws IOException, InterruptedException, TimeoutException { + waitForProcessDuration(timeout); } @Override @@ -91,13 +100,13 @@ void testEmulatorHelper() throws IOException, InterruptedException, TimeoutExcep emulatorRunner.start(); EasyMock.expectLastCall(); EasyMock.expect(emulatorRunner.getProcess()).andReturn(process); - emulatorRunner.waitFor(Duration.ofMinutes(1)); + emulatorRunner.waitForDuration(Duration.ofMinutes(1)); EasyMock.expectLastCall().andReturn(0); EasyMock.replay(process, emulatorRunner); TestEmulatorHelper helper = new TestEmulatorHelper(ImmutableList.of(emulatorRunner), BLOCK_UNTIL); helper.start(); - helper.stop(Duration.ofMinutes(1)); + helper.stopDuration(Duration.ofMinutes(1)); EasyMock.verify(); } @@ -157,13 +166,13 @@ void testEmulatorHelperMultipleRunners() secondRunner.start(); EasyMock.expectLastCall(); EasyMock.expect(secondRunner.getProcess()).andReturn(process); - secondRunner.waitFor(Duration.ofMinutes(1)); + secondRunner.waitForDuration(Duration.ofMinutes(1)); EasyMock.expectLastCall().andReturn(0); EasyMock.replay(process, secondRunner); TestEmulatorHelper helper = new TestEmulatorHelper(ImmutableList.of(firstRunner, secondRunner), BLOCK_UNTIL); helper.start(); - helper.stop(Duration.ofMinutes(1)); + helper.stopDuration(Duration.ofMinutes(1)); EasyMock.verify(); } From 4699df3aec35c700f02271c5b2d51fd6952eb641 Mon Sep 17 00:00:00 2001 From: diegomarquezp Date: Fri, 1 Nov 2024 20:33:18 +0000 Subject: [PATCH 06/16] fix offset parser config --- .../src/main/java/com/google/cloud/Timestamp.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java b/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java index 79c9ff5289..f7b549f99b 100644 --- a/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java +++ b/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java @@ -54,7 +54,7 @@ public final class Timestamp implements Comparable, Serializable { new DateTimeFormatterBuilder() .appendOptional(DateTimeFormatter.ISO_LOCAL_DATE_TIME) .optionalStart() - .appendOffsetId() + .appendZoneOrOffsetId() .optionalEnd() .toFormatter() .withZone(ZoneOffset.UTC); From 656d65291de7d3691cfcdf4fe740da6ea3a4a2dc Mon Sep 17 00:00:00 2001 From: diegomarquezp Date: Mon, 4 Nov 2024 19:56:59 +0000 Subject: [PATCH 07/16] various fixes --- .../clirr-ignored-differences.xml | 1 + .../main/java/com/google/cloud/Timestamp.java | 12 ++++++++- .../cloud/testing/BaseEmulatorHelper.java | 26 +++++-------------- .../java/com/google/cloud/TimestampTest.java | 14 ++++++---- .../cloud/testing/BaseEmulatorHelperTest.java | 2 +- 5 files changed, 28 insertions(+), 27 deletions(-) diff --git a/java-core/google-cloud-core/clirr-ignored-differences.xml b/java-core/google-cloud-core/clirr-ignored-differences.xml index 43b549273f..6792bcb968 100644 --- a/java-core/google-cloud-core/clirr-ignored-differences.xml +++ b/java-core/google-cloud-core/clirr-ignored-differences.xml @@ -13,6 +13,7 @@ long limit() + 7012 com/google/cloud/testing/BaseEmulatorHelper$EmulatorRunner int waitForDuration(java.time.Duration) diff --git a/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java b/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java index f7b549f99b..7c429155b7 100644 --- a/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java +++ b/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java @@ -189,6 +189,16 @@ public com.google.protobuf.Timestamp toProto() { return com.google.protobuf.Timestamp.newBuilder().setSeconds(seconds).setNanos(nanos).build(); } + /** This method is obsolete. Use {@link #parseTimestampDuration(String)} instead */ + public static Timestamp parseTimestamp(String timestamp) { + try { + return parseTimestampDuration(timestamp); + } catch (DateTimeParseException ex) { + throw new org.threeten.bp.format.DateTimeParseException( + ex.getMessage(), ex.getParsedString(), ex.getErrorIndex()); + } + } + /** * Creates a Timestamp instance from the given string. Input string should be in the RFC 3339 * format, like '2020-12-01T10:15:30.000Z' or with the timezone offset, such as @@ -198,7 +208,7 @@ public com.google.protobuf.Timestamp toProto() { * @return created Timestamp * @throws DateTimeParseException if unable to parse */ - public static Timestamp parseTimestamp(String timestamp) { + public static Timestamp parseTimestampDuration(String timestamp) { TemporalAccessor temporalAccessor = timestampParser.parse(timestamp); Instant instant = Instant.from(temporalAccessor); return ofTimeSecondsAndNanos(instant.getEpochSecond(), instant.getNano()); diff --git a/java-core/google-cloud-core/src/main/java/com/google/cloud/testing/BaseEmulatorHelper.java b/java-core/google-cloud-core/src/main/java/com/google/cloud/testing/BaseEmulatorHelper.java index b99b418bf4..8c111cd3fa 100644 --- a/java-core/google-cloud-core/src/main/java/com/google/cloud/testing/BaseEmulatorHelper.java +++ b/java-core/google-cloud-core/src/main/java/com/google/cloud/testing/BaseEmulatorHelper.java @@ -115,18 +115,11 @@ protected final void startProcess(String blockUntilOutput) } } - /** This method is obsolete. Use {@link #waitForProcessDuration(java.time.Duration)} instead */ - @ObsoleteApi("Use waitForProcessDuration() instead") - protected final int waitForProcess(org.threeten.bp.Duration timeout) - throws IOException, InterruptedException, TimeoutException { - return waitForProcessDuration(toJavaTimeDuration(timeout)); - } - /** * Waits for the local service's subprocess to terminate, and stop any possible thread listening * for its output. */ - protected final int waitForProcessDuration(java.time.Duration timeout) + protected final int waitForProcess(java.time.Duration timeout) throws IOException, InterruptedException, TimeoutException { if (activeRunner != null) { int exitCode = activeRunner.waitForDuration(timeout); @@ -140,14 +133,7 @@ protected final int waitForProcessDuration(java.time.Duration timeout) return 0; } - /** This method is obsolete. Use {@link #waitForProcessDuration(java.time.Duration)} instead */ - @ObsoleteApi("Use waitForProcessDuration() instead") - private static int waitForProcess(final Process process, org.threeten.bp.Duration timeout) - throws InterruptedException, TimeoutException { - return waitForProcessDuration(process, toJavaTimeDuration(timeout)); - } - - private static int waitForProcessDuration(final Process process, java.time.Duration timeout) + private static int waitForProcess(final Process process, java.time.Duration timeout) throws InterruptedException, TimeoutException { if (process == null) { return 0; @@ -299,13 +285,13 @@ public void start() throws IOException { @Override public int waitFor(org.threeten.bp.Duration timeout) throws InterruptedException, TimeoutException { - return waitForProcess(process, timeout); + return waitForDuration(toJavaTimeDuration(timeout)); } @Override public int waitForDuration(java.time.Duration timeout) throws InterruptedException, TimeoutException { - return waitForProcessDuration(process, timeout); + return waitForProcess(process, timeout); } @Override @@ -418,12 +404,12 @@ public Path call() throws IOException { @Override public int waitFor(org.threeten.bp.Duration timeout) throws InterruptedException, TimeoutException { - return waitForProcess(process, timeout); + return waitForDuration(toJavaTimeDuration(timeout)); } public int waitForDuration(java.time.Duration timeout) throws InterruptedException, TimeoutException { - return waitForProcessDuration(process, timeout); + return waitForProcess(process, timeout); } @Override diff --git a/java-core/google-cloud-core/src/test/java/com/google/cloud/TimestampTest.java b/java-core/google-cloud-core/src/test/java/com/google/cloud/TimestampTest.java index ba2ad5b701..7313cc2afe 100644 --- a/java-core/google-cloud-core/src/test/java/com/google/cloud/TimestampTest.java +++ b/java-core/google-cloud-core/src/test/java/com/google/cloud/TimestampTest.java @@ -237,14 +237,18 @@ void parseTimestampWithoutTimeZoneOffset() { @Test void parseTimestampWithTimeZoneOffset() { - assertThat(Timestamp.parseTimestamp("0001-01-01T00:00:00-00:00")) + assertThat(Timestamp.parseTimestampDuration("0001-01-01T00:00:00-00:00")) .isEqualTo(Timestamp.MIN_VALUE); - assertThat(Timestamp.parseTimestamp("9999-12-31T23:59:59.999999999-00:00")) + assertThat(Timestamp.parseTimestampDuration("9999-12-31T23:59:59.999999999-00:00")) .isEqualTo(Timestamp.MAX_VALUE); - assertThat(Timestamp.parseTimestamp("2020-12-06T19:21:12.123+05:30")) - .isEqualTo(Timestamp.ofTimeSecondsAndNanos(1607262672, 123000000)); - assertThat(Timestamp.parseTimestamp("2020-07-10T14:03:00-07:00")) + assertThat(Timestamp.parseTimestampDuration("2020-07-10T14:03:00-07:00")) .isEqualTo(Timestamp.ofTimeSecondsAndNanos(1594414980, 0)); + assertThat(Timestamp.parseTimestampDuration("2020-12-06T19:21:12.123+05:30")) + .isEqualTo(Timestamp.ofTimeSecondsAndNanos(1607262672, 123000000)); + // we also confirm that parsing a timestamp with nano precision will behave the same as the + // threeten counterpart + assertThat(Timestamp.parseTimestampDuration("2020-12-06T19:21:12.123+05:30")) + .isEqualTo(Timestamp.parseTimestamp("2020-12-06T19:21:12.123+05:30")); } @Test diff --git a/java-core/google-cloud-core/src/test/java/com/google/cloud/testing/BaseEmulatorHelperTest.java b/java-core/google-cloud-core/src/test/java/com/google/cloud/testing/BaseEmulatorHelperTest.java index beb6e68b85..bc12bc79c6 100644 --- a/java-core/google-cloud-core/src/test/java/com/google/cloud/testing/BaseEmulatorHelperTest.java +++ b/java-core/google-cloud-core/src/test/java/com/google/cloud/testing/BaseEmulatorHelperTest.java @@ -81,7 +81,7 @@ public void stop(org.threeten.bp.Duration timeout) @Override public void stopDuration(Duration timeout) throws IOException, InterruptedException, TimeoutException { - waitForProcessDuration(timeout); + waitForProcess(timeout); } @Override From 2d7950f445c93c77f0999caf190422635e50f1dd Mon Sep 17 00:00:00 2001 From: diegomarquezp Date: Mon, 4 Nov 2024 19:59:48 +0000 Subject: [PATCH 08/16] google-cloud-core/ --- java-core/google-cloud-core/clirr-ignored-differences.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/java-core/google-cloud-core/clirr-ignored-differences.xml b/java-core/google-cloud-core/clirr-ignored-differences.xml index 6792bcb968..984060a817 100644 --- a/java-core/google-cloud-core/clirr-ignored-differences.xml +++ b/java-core/google-cloud-core/clirr-ignored-differences.xml @@ -18,4 +18,12 @@ com/google/cloud/testing/BaseEmulatorHelper$EmulatorRunner int waitForDuration(java.time.Duration) + + + 7005 + com/google/cloud/testing/BaseEmulatorHelper + int waitForProcess(org.threeten.bp.Duration) + int waitForProcess(java.time.Duration) + + From e78ea16b54d22713ed81f56dba8234af03224baf Mon Sep 17 00:00:00 2001 From: diegomarquezp Date: Mon, 4 Nov 2024 20:11:25 +0000 Subject: [PATCH 09/16] restore overload for waitForProcess --- java-core/google-cloud-core/clirr-ignored-differences.xml | 8 -------- .../java/com/google/cloud/testing/BaseEmulatorHelper.java | 8 +++++++- .../com/google/cloud/testing/BaseEmulatorHelperTest.java | 2 +- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/java-core/google-cloud-core/clirr-ignored-differences.xml b/java-core/google-cloud-core/clirr-ignored-differences.xml index 984060a817..6792bcb968 100644 --- a/java-core/google-cloud-core/clirr-ignored-differences.xml +++ b/java-core/google-cloud-core/clirr-ignored-differences.xml @@ -18,12 +18,4 @@ com/google/cloud/testing/BaseEmulatorHelper$EmulatorRunner int waitForDuration(java.time.Duration) - - - 7005 - com/google/cloud/testing/BaseEmulatorHelper - int waitForProcess(org.threeten.bp.Duration) - int waitForProcess(java.time.Duration) - - diff --git a/java-core/google-cloud-core/src/main/java/com/google/cloud/testing/BaseEmulatorHelper.java b/java-core/google-cloud-core/src/main/java/com/google/cloud/testing/BaseEmulatorHelper.java index 8c111cd3fa..872b784896 100644 --- a/java-core/google-cloud-core/src/main/java/com/google/cloud/testing/BaseEmulatorHelper.java +++ b/java-core/google-cloud-core/src/main/java/com/google/cloud/testing/BaseEmulatorHelper.java @@ -115,11 +115,17 @@ protected final void startProcess(String blockUntilOutput) } } + /** This method is obsolete. Use {@link #waitForProcessDuration(java.time.Duration)} instead */ + protected final int waitForProcess(org.threeten.bp.Duration timeout) + throws IOException, InterruptedException, TimeoutException { + return waitForProcessDuration(toJavaTimeDuration(timeout)); + } + /** * Waits for the local service's subprocess to terminate, and stop any possible thread listening * for its output. */ - protected final int waitForProcess(java.time.Duration timeout) + protected final int waitForProcessDuration(java.time.Duration timeout) throws IOException, InterruptedException, TimeoutException { if (activeRunner != null) { int exitCode = activeRunner.waitForDuration(timeout); diff --git a/java-core/google-cloud-core/src/test/java/com/google/cloud/testing/BaseEmulatorHelperTest.java b/java-core/google-cloud-core/src/test/java/com/google/cloud/testing/BaseEmulatorHelperTest.java index bc12bc79c6..beb6e68b85 100644 --- a/java-core/google-cloud-core/src/test/java/com/google/cloud/testing/BaseEmulatorHelperTest.java +++ b/java-core/google-cloud-core/src/test/java/com/google/cloud/testing/BaseEmulatorHelperTest.java @@ -81,7 +81,7 @@ public void stop(org.threeten.bp.Duration timeout) @Override public void stopDuration(Duration timeout) throws IOException, InterruptedException, TimeoutException { - waitForProcess(timeout); + waitForProcessDuration(timeout); } @Override From 1e28055bef35bcd7168cbdf1e0e6c82ad6c1a7e7 Mon Sep 17 00:00:00 2001 From: diegomarquezp Date: Mon, 4 Nov 2024 21:55:16 +0000 Subject: [PATCH 10/16] add obsoelte annotation --- .../src/main/java/com/google/cloud/Timestamp.java | 2 ++ .../main/java/com/google/cloud/testing/BaseEmulatorHelper.java | 1 + 2 files changed, 3 insertions(+) diff --git a/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java b/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java index 7c429155b7..d24cb2a37e 100644 --- a/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java +++ b/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java @@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkArgument; +import com.google.api.core.ObsoleteApi; import com.google.protobuf.util.Timestamps; import java.io.Serializable; import java.time.Instant; @@ -190,6 +191,7 @@ public com.google.protobuf.Timestamp toProto() { } /** This method is obsolete. Use {@link #parseTimestampDuration(String)} instead */ + @ObsoleteApi("Use parseTimestampDuration(String) instead") public static Timestamp parseTimestamp(String timestamp) { try { return parseTimestampDuration(timestamp); diff --git a/java-core/google-cloud-core/src/main/java/com/google/cloud/testing/BaseEmulatorHelper.java b/java-core/google-cloud-core/src/main/java/com/google/cloud/testing/BaseEmulatorHelper.java index 872b784896..93f7ea0f59 100644 --- a/java-core/google-cloud-core/src/main/java/com/google/cloud/testing/BaseEmulatorHelper.java +++ b/java-core/google-cloud-core/src/main/java/com/google/cloud/testing/BaseEmulatorHelper.java @@ -116,6 +116,7 @@ protected final void startProcess(String blockUntilOutput) } /** This method is obsolete. Use {@link #waitForProcessDuration(java.time.Duration)} instead */ + @ObsoleteApi("Use waitForProcessDuration(java.time.Duration) instead") protected final int waitForProcess(org.threeten.bp.Duration timeout) throws IOException, InterruptedException, TimeoutException { return waitForProcessDuration(toJavaTimeDuration(timeout)); From be1ff27216f61d66ffffcee5b465fb67bcb2b88b Mon Sep 17 00:00:00 2001 From: diegomarquezp Date: Mon, 4 Nov 2024 22:14:41 +0000 Subject: [PATCH 11/16] restore timestamp offset parser --- .../src/main/java/com/google/cloud/Timestamp.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java b/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java index d24cb2a37e..5e8d5d7b3a 100644 --- a/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java +++ b/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java @@ -55,7 +55,7 @@ public final class Timestamp implements Comparable, Serializable { new DateTimeFormatterBuilder() .appendOptional(DateTimeFormatter.ISO_LOCAL_DATE_TIME) .optionalStart() - .appendZoneOrOffsetId() + .appendOffsetId() .optionalEnd() .toFormatter() .withZone(ZoneOffset.UTC); From 685a3e91236f29c29cae42cc37ccdd1ed30a1e54 Mon Sep 17 00:00:00 2001 From: diegomarquezp Date: Mon, 4 Nov 2024 22:24:15 +0000 Subject: [PATCH 12/16] use alternative offset method --- .../src/main/java/com/google/cloud/Timestamp.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java b/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java index 5e8d5d7b3a..06efc87bd7 100644 --- a/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java +++ b/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java @@ -55,7 +55,7 @@ public final class Timestamp implements Comparable, Serializable { new DateTimeFormatterBuilder() .appendOptional(DateTimeFormatter.ISO_LOCAL_DATE_TIME) .optionalStart() - .appendOffsetId() + .appendOffset("+HH:MM", "Z") .optionalEnd() .toFormatter() .withZone(ZoneOffset.UTC); From 7661f0a8b472501cd02c2f8068e85b41b4132bcd Mon Sep 17 00:00:00 2001 From: diegomarquezp Date: Tue, 5 Nov 2024 23:16:09 +0000 Subject: [PATCH 13/16] add zone string test --- .../src/main/java/com/google/cloud/Timestamp.java | 2 +- .../src/test/java/com/google/cloud/TimestampTest.java | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java b/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java index 06efc87bd7..d24cb2a37e 100644 --- a/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java +++ b/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java @@ -55,7 +55,7 @@ public final class Timestamp implements Comparable, Serializable { new DateTimeFormatterBuilder() .appendOptional(DateTimeFormatter.ISO_LOCAL_DATE_TIME) .optionalStart() - .appendOffset("+HH:MM", "Z") + .appendZoneOrOffsetId() .optionalEnd() .toFormatter() .withZone(ZoneOffset.UTC); diff --git a/java-core/google-cloud-core/src/test/java/com/google/cloud/TimestampTest.java b/java-core/google-cloud-core/src/test/java/com/google/cloud/TimestampTest.java index 7313cc2afe..c340519e07 100644 --- a/java-core/google-cloud-core/src/test/java/com/google/cloud/TimestampTest.java +++ b/java-core/google-cloud-core/src/test/java/com/google/cloud/TimestampTest.java @@ -251,6 +251,12 @@ void parseTimestampWithTimeZoneOffset() { .isEqualTo(Timestamp.parseTimestamp("2020-12-06T19:21:12.123+05:30")); } + @Test + void parseTimestampWithZoneString() { + assertThat(Timestamp.parseTimestampDuration("2020-12-06T08:51:12.123America/Toronto")) + .isEqualTo(Timestamp.ofTimeSecondsAndNanos(1607262672, 123000000)); + } + @Test void fromProto() { com.google.protobuf.Timestamp proto = From a90bf83b4faa8fd3bf9ff7b1513b6c600a0692e4 Mon Sep 17 00:00:00 2001 From: Diego Alonso Marquez Palacios Date: Wed, 6 Nov 2024 17:45:20 -0500 Subject: [PATCH 14/16] expand offset and zone tests --- .../java/com/google/cloud/TimestampTest.java | 46 ++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/java-core/google-cloud-core/src/test/java/com/google/cloud/TimestampTest.java b/java-core/google-cloud-core/src/test/java/com/google/cloud/TimestampTest.java index c340519e07..354a389ff2 100644 --- a/java-core/google-cloud-core/src/test/java/com/google/cloud/TimestampTest.java +++ b/java-core/google-cloud-core/src/test/java/com/google/cloud/TimestampTest.java @@ -22,6 +22,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import com.google.common.testing.EqualsTester; +import java.time.format.DateTimeParseException; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; @@ -237,24 +238,67 @@ void parseTimestampWithoutTimeZoneOffset() { @Test void parseTimestampWithTimeZoneOffset() { + // Max values assertThat(Timestamp.parseTimestampDuration("0001-01-01T00:00:00-00:00")) .isEqualTo(Timestamp.MIN_VALUE); assertThat(Timestamp.parseTimestampDuration("9999-12-31T23:59:59.999999999-00:00")) .isEqualTo(Timestamp.MAX_VALUE); + // Extreme values (close to min/max) + assertThat(Timestamp.parseTimestampDuration("0001-01-01T00:00:00.000000001Z")) + .isEqualTo(Timestamp.ofTimeSecondsAndNanos(Timestamp.MIN_VALUE.getSeconds(), 1)); + assertThat(Timestamp.parseTimestampDuration("9999-12-31T23:59:59.999999998Z")) + .isEqualTo(Timestamp.ofTimeSecondsAndNanos(Timestamp.MAX_VALUE.getSeconds(), 999999998)); + // Common use cases assertThat(Timestamp.parseTimestampDuration("2020-07-10T14:03:00-07:00")) .isEqualTo(Timestamp.ofTimeSecondsAndNanos(1594414980, 0)); assertThat(Timestamp.parseTimestampDuration("2020-12-06T19:21:12.123+05:30")) .isEqualTo(Timestamp.ofTimeSecondsAndNanos(1607262672, 123000000)); - // we also confirm that parsing a timestamp with nano precision will behave the same as the + // We also confirm that parsing a timestamp with nano precision will behave the same as the // threeten counterpart assertThat(Timestamp.parseTimestampDuration("2020-12-06T19:21:12.123+05:30")) .isEqualTo(Timestamp.parseTimestamp("2020-12-06T19:21:12.123+05:30")); + // Timestamps with fractional seconds at nanosecond level + assertThat(Timestamp.parseTimestampDuration("2020-12-06T19:21:12.123456789+05:30")) + .isEqualTo(Timestamp.ofTimeSecondsAndNanos(1607262672, 123456789)); + // Fractional seconds beyond nanos should throw an exception + assertThrows( + DateTimeParseException.class, + () -> Timestamp.parseTimestampDuration("2020-12-06T19:21:12.123456789321+05:30")); + // Missing components (should throw exceptions) + assertThrows( + DateTimeParseException.class, () -> Timestamp.parseTimestampDuration("2020-12-06")); + // Whitespace should not be supported + assertThrows( + DateTimeParseException.class, + () -> Timestamp.parseTimestampDuration(" 2020-12-06T19:21:12.123+05:30 ")); + // It should be case-insensitive + assertThat(Timestamp.parseTimestampDuration("2020-07-10t14:03:00-07:00")) + .isEqualTo(Timestamp.ofTimeSecondsAndNanos(1594414980, 0)); + // Invalid time zone offsets + assertThrows( + DateTimeParseException.class, + () -> Timestamp.parseTimestampDuration("2020-12-06T19:21:12.123+25:00")); + assertThrows( + DateTimeParseException.class, + () -> Timestamp.parseTimestampDuration("2020-12-06T19:21:12.123-25:00")); + // Int values for SecondOfMinute should be between 0 and 59 + assertThrows( + DateTimeParseException.class, + () -> Timestamp.parseTimestampDuration("2016-12-31T23:59:60Z")); } @Test void parseTimestampWithZoneString() { + // Valid RFC 3339 timestamps with time zone names assertThat(Timestamp.parseTimestampDuration("2020-12-06T08:51:12.123America/Toronto")) .isEqualTo(Timestamp.ofTimeSecondsAndNanos(1607262672, 123000000)); + assertThat(Timestamp.parseTimestampDuration("2023-04-10T22:42:10.123456789Europe/London")) + .isEqualTo(Timestamp.ofTimeSecondsAndNanos(1681162930, 123456789)); + + // Invalid time zone names + assertThrows( + DateTimeParseException.class, + () -> Timestamp.parseTimestampDuration("2020-12-06T19:21:12.123Invalid/TimeZone")); } @Test From b67db509d5f121a42b70eec1dd5824358053d973 Mon Sep 17 00:00:00 2001 From: Diego Alonso Marquez Palacios Date: Thu, 7 Nov 2024 11:51:21 -0500 Subject: [PATCH 15/16] fix test case --- .../src/test/java/com/google/cloud/TimestampTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java-core/google-cloud-core/src/test/java/com/google/cloud/TimestampTest.java b/java-core/google-cloud-core/src/test/java/com/google/cloud/TimestampTest.java index 354a389ff2..f6926f444f 100644 --- a/java-core/google-cloud-core/src/test/java/com/google/cloud/TimestampTest.java +++ b/java-core/google-cloud-core/src/test/java/com/google/cloud/TimestampTest.java @@ -249,8 +249,8 @@ void parseTimestampWithTimeZoneOffset() { assertThat(Timestamp.parseTimestampDuration("9999-12-31T23:59:59.999999998Z")) .isEqualTo(Timestamp.ofTimeSecondsAndNanos(Timestamp.MAX_VALUE.getSeconds(), 999999998)); // Common use cases - assertThat(Timestamp.parseTimestampDuration("2020-07-10T14:03:00-07:00")) - .isEqualTo(Timestamp.ofTimeSecondsAndNanos(1594414980, 0)); + assertThat(Timestamp.parseTimestampDuration("2020-07-10T14:03:00.123-07:00")) + .isEqualTo(Timestamp.ofTimeSecondsAndNanos(1594414980, 123000000)); assertThat(Timestamp.parseTimestampDuration("2020-12-06T19:21:12.123+05:30")) .isEqualTo(Timestamp.ofTimeSecondsAndNanos(1607262672, 123000000)); // We also confirm that parsing a timestamp with nano precision will behave the same as the From 26437b72c3d1c816615a83557c8354bd3dc8ffb5 Mon Sep 17 00:00:00 2001 From: diegomarquezp Date: Thu, 7 Nov 2024 17:15:24 +0000 Subject: [PATCH 16/16] chore: demo offset parsing tests in java-core + java.time --- .../src/main/java/com/google/cloud/Timestamp.java | 3 ++- .../test/java/com/google/cloud/TimestampTest.java | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java b/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java index d24cb2a37e..dbeea88616 100644 --- a/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java +++ b/java-core/google-cloud-core/src/main/java/com/google/cloud/Timestamp.java @@ -55,7 +55,8 @@ public final class Timestamp implements Comparable, Serializable { new DateTimeFormatterBuilder() .appendOptional(DateTimeFormatter.ISO_LOCAL_DATE_TIME) .optionalStart() - .appendZoneOrOffsetId() + // .appendZoneOrOffsetId() + .appendOffsetId() .optionalEnd() .toFormatter() .withZone(ZoneOffset.UTC); diff --git a/java-core/google-cloud-core/src/test/java/com/google/cloud/TimestampTest.java b/java-core/google-cloud-core/src/test/java/com/google/cloud/TimestampTest.java index f6926f444f..185340ae29 100644 --- a/java-core/google-cloud-core/src/test/java/com/google/cloud/TimestampTest.java +++ b/java-core/google-cloud-core/src/test/java/com/google/cloud/TimestampTest.java @@ -287,6 +287,18 @@ void parseTimestampWithTimeZoneOffset() { () -> Timestamp.parseTimestampDuration("2016-12-31T23:59:60Z")); } + @Test + void demoAssertion1() { + assertThat(Timestamp.parseTimestampDuration("2020-07-10T14:03:00.123-07:00")) + .isEqualTo(Timestamp.ofTimeSecondsAndNanos(1594414980, 123000000)); + } + + @Test + void demoAssertion2() { + assertThat(Timestamp.parseTimestampDuration("2020-12-06T19:21:12.123+05:30")) + .isEqualTo(Timestamp.ofTimeSecondsAndNanos(1607262672, 123000000)); + } + @Test void parseTimestampWithZoneString() { // Valid RFC 3339 timestamps with time zone names