Move the DurationConverter to the common.options package

Also change it to java.time.Duration, rather than Jodatime. Now that we're on
Java 8, we no longer need Jodatime.

PiperOrigin-RevId: 162917526
diff --git a/src/main/java/com/google/devtools/build/lib/BUILD b/src/main/java/com/google/devtools/build/lib/BUILD
index e0c6a93..49992e1 100644
--- a/src/main/java/com/google/devtools/build/lib/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/BUILD
@@ -377,7 +377,6 @@
         "//src/main/java/com/google/devtools/build/lib/buildeventstream/transports",
         "//src/main/java/com/google/devtools/common/options",
         "//third_party:guava",
-        "//third_party:joda_time",
         "//third_party:jsr305",
         "//third_party/grpc:grpc-jar",
         "@com_google_protobuf//:protobuf_java",
diff --git a/src/main/java/com/google/devtools/build/lib/buildeventservice/BuildEventServiceOptions.java b/src/main/java/com/google/devtools/build/lib/buildeventservice/BuildEventServiceOptions.java
index 9c67f30..e24c204 100644
--- a/src/main/java/com/google/devtools/build/lib/buildeventservice/BuildEventServiceOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/buildeventservice/BuildEventServiceOptions.java
@@ -14,15 +14,11 @@
 
 package com.google.devtools.build.lib.buildeventservice;
 
-import com.google.devtools.common.options.Converter;
 import com.google.devtools.common.options.Option;
 import com.google.devtools.common.options.OptionDocumentationCategory;
 import com.google.devtools.common.options.OptionEffectTag;
 import com.google.devtools.common.options.OptionsBase;
-import com.google.devtools.common.options.OptionsParsingException;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import org.joda.time.Duration;
+import java.time.Duration;
 
 /** Options used by {@link BuildEventServiceModule}. */
 public class BuildEventServiceOptions extends OptionsBase {
@@ -41,7 +37,6 @@
   @Option(
     name = "bes_timeout",
     defaultValue = "0s",
-    converter = DurationConverter.class,
     documentationCategory = OptionDocumentationCategory.LOGGING,
     effectTags = {OptionEffectTag.AFFECTS_OUTPUTS},
     help =
@@ -81,47 +76,4 @@
     help = "Specifies the BES project identifier. Defaults to null."
   )
   public String projectId;
-
-  /**
-   * Simple String to Duration Converter.
-   */
-  public static class DurationConverter implements Converter<Duration> {
-
-    private final Pattern durationRegex = Pattern.compile("^([0-9]+)(d|h|m|s|ms)$");
-
-    @Override
-    public Duration convert(String input) throws OptionsParsingException {
-      // To be compatible with the previous parser, '0' doesn't need a unit.
-      if ("0".equals(input)) {
-        return Duration.ZERO;
-      }
-      Matcher m = durationRegex.matcher(input);
-      if (!m.matches()) {
-        throw new OptionsParsingException("Illegal duration '" + input + "'.");
-      }
-      long duration = Long.parseLong(m.group(1));
-      String unit = m.group(2);
-      switch(unit) {
-        case "d":
-          return Duration.standardDays(duration);
-        case "h":
-          return Duration.standardHours(duration);
-        case "m":
-          return Duration.standardMinutes(duration);
-        case "s":
-          return Duration.standardSeconds(duration);
-        case "ms":
-          return Duration.millis(duration);
-        default:
-          throw new IllegalStateException("This must not happen. Did you update the regex without "
-              + "the switch case?");
-      }
-    }
-
-    @Override
-    public String getTypeDescription() {
-      return "An immutable length of time.";
-    }
-  }
-
 }
diff --git a/src/main/java/com/google/devtools/build/lib/buildeventservice/BuildEventServiceTransport.java b/src/main/java/com/google/devtools/build/lib/buildeventservice/BuildEventServiceTransport.java
index 0cf67ba..b7c8ce7 100644
--- a/src/main/java/com/google/devtools/build/lib/buildeventservice/BuildEventServiceTransport.java
+++ b/src/main/java/com/google/devtools/build/lib/buildeventservice/BuildEventServiceTransport.java
@@ -25,7 +25,6 @@
 import static com.google.devtools.build.v1.BuildStatus.Result.UNKNOWN_STATUS;
 import static java.lang.String.format;
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static org.joda.time.Duration.standardSeconds;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Function;
@@ -55,6 +54,7 @@
 import com.google.devtools.build.v1.PublishLifecycleEventRequest;
 import com.google.protobuf.Any;
 import io.grpc.Status;
+import java.time.Duration;
 import java.util.Deque;
 import java.util.concurrent.BlockingDeque;
 import java.util.concurrent.Callable;
@@ -69,7 +69,6 @@
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import javax.annotation.Nullable;
-import org.joda.time.Duration;
 
 /** A {@link BuildEventTransport} that streams {@link BuildEvent}s to BuildEventService. */
 public class BuildEventServiceTransport implements BuildEventTransport {
@@ -81,7 +80,7 @@
   private static final Logger logger = Logger.getLogger(BuildEventServiceTransport.class.getName());
 
   /** Max wait time until for the Streaming RPC to finish after all events were enqueued. */
-  private static final Duration PUBLISH_EVENT_STREAM_FINISHED_TIMEOUT = standardSeconds(120);
+  private static final Duration PUBLISH_EVENT_STREAM_FINISHED_TIMEOUT = Duration.ofSeconds(120);
 
   private final ListeningExecutorService uploaderExecutorService;
   private final Duration uploadTimeout;
@@ -206,7 +205,7 @@
                 if (Duration.ZERO.equals(uploadTimeout)) {
                   uploadComplete.get();
                 } else {
-                  uploadComplete.get(uploadTimeout.getMillis(), MILLISECONDS);
+                  uploadComplete.get(uploadTimeout.toMillis(), MILLISECONDS);
                 }
                 report(INFO, UPLOAD_SUCCEEDED_MESSAGE);
               } catch (Exception e) {
@@ -407,7 +406,7 @@
     pendingAck = new ConcurrentLinkedDeque<>();
 
     return publishEventStream(pendingAck, pendingSend, besClient)
-        .get(PUBLISH_EVENT_STREAM_FINISHED_TIMEOUT.getMillis(), TimeUnit.MILLISECONDS);
+        .get(PUBLISH_EVENT_STREAM_FINISHED_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS);
   }
 
   /** Method responsible for a single Streaming RPC. */
diff --git a/src/main/java/com/google/devtools/common/options/Converters.java b/src/main/java/com/google/devtools/common/options/Converters.java
index 4584f80..aacc64b 100644
--- a/src/main/java/com/google/devtools/common/options/Converters.java
+++ b/src/main/java/com/google/devtools/common/options/Converters.java
@@ -16,10 +16,12 @@
 import com.google.common.base.Splitter;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Maps;
+import java.time.Duration;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.logging.Level;
+import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
 
@@ -178,6 +180,47 @@
   }
 
   /**
+   * Standard converter for the {@link java.time.Duration} type.
+   */
+  public static class DurationConverter implements Converter<Duration> {
+    private final Pattern durationRegex = Pattern.compile("^([0-9]+)(d|h|m|s|ms)$");
+
+    @Override
+    public Duration convert(String input) throws OptionsParsingException {
+      // To be compatible with the previous parser, '0' doesn't need a unit.
+      if ("0".equals(input)) {
+        return Duration.ZERO;
+      }
+      Matcher m = durationRegex.matcher(input);
+      if (!m.matches()) {
+        throw new OptionsParsingException("Illegal duration '" + input + "'.");
+      }
+      long duration = Long.parseLong(m.group(1));
+      String unit = m.group(2);
+      switch(unit) {
+        case "d":
+          return Duration.ofDays(duration);
+        case "h":
+          return Duration.ofHours(duration);
+        case "m":
+          return Duration.ofMinutes(duration);
+        case "s":
+          return Duration.ofSeconds(duration);
+        case "ms":
+          return Duration.ofMillis(duration);
+        default:
+          throw new IllegalStateException("This must not happen. Did you update the regex without "
+              + "the switch case?");
+      }
+    }
+
+    @Override
+    public String getTypeDescription() {
+      return "An immutable length of time.";
+    }
+  }
+
+  /**
    * The converters that are available to the options parser by default. These are used if the
    * {@code @Option} annotation does not specify its own {@code converter}, and its type is one of
    * the following.
@@ -185,12 +228,14 @@
   static final Map<Class<?>, Converter<?>> DEFAULT_CONVERTERS = Maps.newHashMap();
 
   static {
+    // 1:1 correspondence with UsesOnlyCoreTypes.CORE_TYPES.
     DEFAULT_CONVERTERS.put(String.class, new Converters.StringConverter());
     DEFAULT_CONVERTERS.put(int.class, new Converters.IntegerConverter());
     DEFAULT_CONVERTERS.put(long.class, new Converters.LongConverter());
     DEFAULT_CONVERTERS.put(double.class, new Converters.DoubleConverter());
     DEFAULT_CONVERTERS.put(boolean.class, new Converters.BooleanConverter());
     DEFAULT_CONVERTERS.put(TriState.class, new Converters.TriStateConverter());
+    DEFAULT_CONVERTERS.put(Duration.class, new Converters.DurationConverter());
     DEFAULT_CONVERTERS.put(Void.class, new Converters.VoidConverter());
   }
 
diff --git a/src/main/java/com/google/devtools/common/options/UsesOnlyCoreTypes.java b/src/main/java/com/google/devtools/common/options/UsesOnlyCoreTypes.java
index 6f2714f..c40495d 100644
--- a/src/main/java/com/google/devtools/common/options/UsesOnlyCoreTypes.java
+++ b/src/main/java/com/google/devtools/common/options/UsesOnlyCoreTypes.java
@@ -20,6 +20,7 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
+import java.time.Duration;
 import java.util.List;
 
 /**
@@ -52,6 +53,7 @@
       double.class,
       boolean.class,
       TriState.class,
-      Void.class
+      Void.class,
+      Duration.class
   );
 }