You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by gg...@apache.org on 2021/02/17 23:06:50 UTC

[httpcomponents-core] branch 5.2.x updated: Let TimeValue convert to and from Duration.

This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch 5.2.x
in repository https://gitbox.apache.org/repos/asf/httpcomponents-core.git


The following commit(s) were added to refs/heads/5.2.x by this push:
     new 05b344b  Let TimeValue convert to and from Duration.
05b344b is described below

commit 05b344b0c56d9def33cb340eb4844bddfe5de61b
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Tue Feb 16 13:58:43 2021 -0500

    Let TimeValue convert to and from Duration.
---
 .../java/org/apache/hc/core5/util/TimeValue.java   | 74 ++++++++++++++++++-
 .../java/org/apache/hc/core5/util/Timeout.java     | 32 +++++++++
 .../org/apache/hc/core5/util/TestTimeValue.java    | 83 ++++++++++++++--------
 .../java/org/apache/hc/core5/util/TestTimeout.java | 16 +++++
 4 files changed, 175 insertions(+), 30 deletions(-)

diff --git a/httpcore5/src/main/java/org/apache/hc/core5/util/TimeValue.java b/httpcore5/src/main/java/org/apache/hc/core5/util/TimeValue.java
index 7071a91..2b2ba00 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/util/TimeValue.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/util/TimeValue.java
@@ -28,7 +28,10 @@
 package org.apache.hc.core5.util;
 
 import java.text.ParseException;
+import java.time.Duration;
+import java.time.temporal.ChronoUnit;
 import java.util.Locale;
+import java.util.Objects;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.hc.core5.annotation.Contract;
@@ -141,13 +144,44 @@ public class TimeValue implements Comparable<TimeValue> {
      * Creates a TimeValue.
      *
      * @param duration the time duration in the given {@code timeUnit}.
-     * @param timeUnit the time unit for the given durarion.
-     * @return a Timeout
+     * @param timeUnit the time unit for the given duration.
+     * @return a Timeout.
      */
     public static TimeValue of(final long duration, final TimeUnit timeUnit) {
         return new TimeValue(duration, timeUnit);
     }
 
+    /**
+     * Creates a TimeValue from a Duration.
+     *
+     * @param duration the time duration in the given {@code timeUnit}.
+     * @param timeUnit the time unit for the given duration.
+     * @return a Timeout
+     * @since 5.2
+     */
+    public static TimeValue of(final Duration duration) {
+        final long seconds = duration.getSeconds();
+        final long nanoOfSecond = duration.getNano();
+        if (seconds == 0) {
+            // no conversion
+            return of(nanoOfSecond, TimeUnit.NANOSECONDS);
+        } else if (nanoOfSecond == 0) {
+            // no conversion
+            return of(seconds, TimeUnit.SECONDS);
+        }
+        // conversion attempts
+        try {
+            return of(duration.toNanos(), TimeUnit.NANOSECONDS);
+        } catch (final ArithmeticException e) {
+            try {
+                return of(duration.toMillis(), TimeUnit.MILLISECONDS);
+            } catch (final ArithmeticException e1) {
+                // backstop
+                return of(seconds, TimeUnit.SECONDS);
+            }
+        }
+    }
+
     public static TimeValue ofDays(final long days) {
         return of(days, TimeUnit.DAYS);
     }
@@ -177,6 +211,32 @@ public class TimeValue implements Comparable<TimeValue> {
     }
 
     /**
+     * Converts a {@link TimeUnit} to the equivalent {@link ChronoUnit}.
+     *
+     * @return the converted equivalent ChronoUnit
+     */
+    static ChronoUnit toChronoUnit(final TimeUnit timeUnit) {
+        switch (Objects.requireNonNull(timeUnit)) {
+        case NANOSECONDS:
+            return ChronoUnit.NANOS;
+        case MICROSECONDS:
+            return ChronoUnit.MICROS;
+        case MILLISECONDS:
+            return ChronoUnit.MILLIS;
+        case SECONDS:
+            return ChronoUnit.SECONDS;
+        case MINUTES:
+            return ChronoUnit.MINUTES;
+        case HOURS:
+            return ChronoUnit.HOURS;
+        case DAYS:
+            return ChronoUnit.DAYS;
+        default:
+            throw new IllegalArgumentException(timeUnit.toString());
+        }
+    }
+
+    /**
      * Parses a TimeValue in the format {@code <Long><SPACE><TimeUnit>}, for example {@code "1200 MILLISECONDS"}.
      * <p>
      * Parses:
@@ -335,6 +395,16 @@ public class TimeValue implements Comparable<TimeValue> {
         return timeUnit.toDays(duration);
     }
 
+    /**
+     * Converts this instance of to a Duration.
+     *
+     * @return a Duration.
+     * @since 5.2
+     */
+    public Duration toDuration() {
+        return duration == 0 ? Duration.ZERO : Duration.of(duration, toChronoUnit(timeUnit));
+    }
+
     public long toHours() {
         return timeUnit.toHours(duration);
     }
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/util/Timeout.java b/httpcore5/src/main/java/org/apache/hc/core5/util/Timeout.java
index 77619f6..0943369 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/util/Timeout.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/util/Timeout.java
@@ -28,6 +28,7 @@
 package org.apache.hc.core5.util;
 
 import java.text.ParseException;
+import java.time.Duration;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.hc.core5.annotation.Contract;
@@ -67,6 +68,37 @@ public class Timeout extends TimeValue {
     }
 
     /**
+     * Creates a Timeout from a Duration.
+     *
+     * @param duration the time duration in the given {@code timeUnit}.
+     * @param timeUnit the time unit for the given duration.
+     * @return a Timeout.
+     * @since 5.2
+     */
+    public static Timeout of(final Duration duration) {
+        final long seconds = duration.getSeconds();
+        final long nanoOfSecond = duration.getNano();
+        if (seconds == 0) {
+            // no conversion
+            return of(nanoOfSecond, TimeUnit.NANOSECONDS);
+        } else if (nanoOfSecond == 0) {
+            // no conversion
+            return of(seconds, TimeUnit.SECONDS);
+        }
+        // conversion attempts
+        try {
+            return of(duration.toNanos(), TimeUnit.NANOSECONDS);
+        } catch (final ArithmeticException e) {
+            try {
+                return of(duration.toMillis(), TimeUnit.MILLISECONDS);
+            } catch (final ArithmeticException e1) {
+                // backstop
+                return of(seconds, TimeUnit.SECONDS);
+            }
+        }
+    }
+
+    /**
      * Creates a Timeout.
      *
      * @param duration the time duration in the given {@code timeUnit}.
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/util/TestTimeValue.java b/httpcore5/src/test/java/org/apache/hc/core5/util/TestTimeValue.java
index 18bc451..be53eac 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/util/TestTimeValue.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/util/TestTimeValue.java
@@ -28,9 +28,11 @@
 package org.apache.hc.core5.util;
 
 import java.text.ParseException;
+import java.time.Duration;
 import java.util.concurrent.TimeUnit;
 
 import org.hamcrest.CoreMatchers;
+import org.hamcrest.MatcherAssert;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -118,6 +120,9 @@ public class TestTimeValue {
 
     private void testFactory(final TimeUnit timeUnit) {
         Assert.assertEquals(timeUnit, TimeValue.of(1, timeUnit).getTimeUnit());
+        //
+        final Duration duration = Duration.of(1, TimeValue.toChronoUnit(timeUnit));
+        assertConvertion(duration);
     }
 
     @Test
@@ -126,6 +131,21 @@ public class TestTimeValue {
     }
 
     @Test
+    public void testFactoryForDuration() {
+        assertConvertion(Duration.ZERO);
+        assertConvertion(Duration.ofDays(1));
+        assertConvertion(Duration.ofHours(1));
+        assertConvertion(Duration.ofMillis(1));
+        assertConvertion(Duration.ofNanos(1));
+        assertConvertion(Duration.ofSeconds(1));
+        assertConvertion(Duration.ofSeconds(1, 1));
+    }
+
+    private void assertConvertion(final Duration duration) {
+        Assert.assertEquals(duration, TimeValue.of(duration).toDuration());
+    }
+
+    @Test
     public void testFactoryForHours() {
         testFactory(TimeUnit.HOURS);
     }
@@ -253,41 +273,47 @@ public class TestTimeValue {
 
     @Test
     public void testFromString() throws ParseException {
-        Assert.assertEquals(TimeValue.ofSeconds(Long.MAX_VALUE), TimeValue.parse("9223372036854775807 SECONDS"));
-        Assert.assertEquals(TimeValue.ofSeconds(Long.MAX_VALUE), TimeValue.parse("9223372036854775807 SECONDS"));
-        Assert.assertEquals(TimeValue.ofSeconds(Long.MAX_VALUE), TimeValue.parse(" 9223372036854775807 SECONDS "));
-        Assert.assertEquals(TimeValue.ofSeconds(Long.MAX_VALUE), TimeValue.parse("9223372036854775807 Seconds"));
-        Assert.assertEquals(TimeValue.ofSeconds(Long.MAX_VALUE), TimeValue.parse("9223372036854775807  Seconds"));
-        Assert.assertEquals(TimeValue.ofSeconds(Long.MAX_VALUE), TimeValue.parse("9223372036854775807\tSeconds"));
+        final TimeValue maxSeconds = TimeValue.ofSeconds(Long.MAX_VALUE);
+        Assert.assertEquals(maxSeconds, TimeValue.parse("9223372036854775807 SECONDS"));
+        Assert.assertEquals(maxSeconds, TimeValue.parse("9223372036854775807 SECONDS"));
+        Assert.assertEquals(maxSeconds, TimeValue.parse(" 9223372036854775807 SECONDS "));
+        Assert.assertEquals(maxSeconds, TimeValue.parse("9223372036854775807 Seconds"));
+        Assert.assertEquals(maxSeconds, TimeValue.parse("9223372036854775807  Seconds"));
+        Assert.assertEquals(maxSeconds, TimeValue.parse("9223372036854775807\tSeconds"));
         Assert.assertEquals(TimeValue.ZERO_MILLISECONDS, TimeValue.parse("0 MILLISECONDS"));
         Assert.assertEquals(TimeValue.ofMilliseconds(1), TimeValue.parse("1 MILLISECOND"));
     }
 
     @Test
-    public void testEqualsAndHashCode() throws ParseException {
+    public void testToDuration() throws ParseException {
+        Assert.assertEquals(Long.MAX_VALUE, TimeValue.parse("9223372036854775807 SECONDS").toDuration().getSeconds());
+    }
+
+    @Test
+    public void testEqualsAndHashCode() {
         final TimeValue tv1 = TimeValue.ofMilliseconds(1000L);
         final TimeValue tv2 = TimeValue.ofMilliseconds(1001L);
         final TimeValue tv3 = TimeValue.ofMilliseconds(1000L);
         final TimeValue tv4 = TimeValue.ofSeconds(1L);
         final TimeValue tv5 = TimeValue.ofSeconds(1000L);
 
-        Assert.assertThat(tv1.equals(tv1), CoreMatchers.equalTo(true));
-        Assert.assertThat(tv1.equals(null), CoreMatchers.equalTo(false));
-        Assert.assertThat(tv1.equals(tv2), CoreMatchers.equalTo(false));
-        Assert.assertThat(tv1.equals(tv3), CoreMatchers.equalTo(true));
-        Assert.assertThat(tv1.equals(tv4), CoreMatchers.equalTo(true));
-        Assert.assertThat(tv4.equals(tv1), CoreMatchers.equalTo(true));
-        Assert.assertThat(tv1.equals(tv5), CoreMatchers.equalTo(false));
-
-        Assert.assertThat(tv1.hashCode() == tv2.hashCode(), CoreMatchers.equalTo(false));
-        Assert.assertThat(tv1.hashCode() == tv3.hashCode(), CoreMatchers.equalTo(true));
-        Assert.assertThat(tv1.hashCode() == tv4.hashCode(), CoreMatchers.equalTo(true));
-        Assert.assertThat(tv4.hashCode() == tv1.hashCode(), CoreMatchers.equalTo(true));
-        Assert.assertThat(tv1.hashCode() == tv5.hashCode(), CoreMatchers.equalTo(false));
+        MatcherAssert.assertThat(tv1.equals(tv1), CoreMatchers.equalTo(true));
+        MatcherAssert.assertThat(tv1.equals(null), CoreMatchers.equalTo(false));
+        MatcherAssert.assertThat(tv1.equals(tv2), CoreMatchers.equalTo(false));
+        MatcherAssert.assertThat(tv1.equals(tv3), CoreMatchers.equalTo(true));
+        MatcherAssert.assertThat(tv1.equals(tv4), CoreMatchers.equalTo(true));
+        MatcherAssert.assertThat(tv4.equals(tv1), CoreMatchers.equalTo(true));
+        MatcherAssert.assertThat(tv1.equals(tv5), CoreMatchers.equalTo(false));
+
+        MatcherAssert.assertThat(tv1.hashCode() == tv2.hashCode(), CoreMatchers.equalTo(false));
+        MatcherAssert.assertThat(tv1.hashCode() == tv3.hashCode(), CoreMatchers.equalTo(true));
+        MatcherAssert.assertThat(tv1.hashCode() == tv4.hashCode(), CoreMatchers.equalTo(true));
+        MatcherAssert.assertThat(tv4.hashCode() == tv1.hashCode(), CoreMatchers.equalTo(true));
+        MatcherAssert.assertThat(tv1.hashCode() == tv5.hashCode(), CoreMatchers.equalTo(false));
     }
 
     @Test
-    public void testCompareTo() throws ParseException {
+    public void testCompareTo() {
         final TimeValue tv1 = TimeValue.ofMilliseconds(1000L);
         final TimeValue tv2 = TimeValue.ofMilliseconds(1001L);
         final TimeValue tv3 = TimeValue.ofMilliseconds(1000L);
@@ -295,17 +321,18 @@ public class TestTimeValue {
         final TimeValue tv5 = TimeValue.ofSeconds(60L);
         final TimeValue tv6 = TimeValue.ofMinutes(1L);
 
-        Assert.assertThat(tv1.compareTo(tv1) == 0, CoreMatchers.equalTo(true));
-        Assert.assertThat(tv1.compareTo(tv2) < 0, CoreMatchers.equalTo(true));
-        Assert.assertThat(tv1.compareTo(tv3) == 0, CoreMatchers.equalTo(true));
-        Assert.assertThat(tv1.compareTo(tv4) == 0, CoreMatchers.equalTo(true));
-        Assert.assertThat(tv1.compareTo(tv5) < 0, CoreMatchers.equalTo(true));
-        Assert.assertThat(tv6.compareTo(tv5) == 0, CoreMatchers.equalTo(true));
-        Assert.assertThat(tv6.compareTo(tv4) > 0, CoreMatchers.equalTo(true));
+        MatcherAssert.assertThat(tv1.compareTo(tv1) == 0, CoreMatchers.equalTo(true));
+        MatcherAssert.assertThat(tv1.compareTo(tv2) < 0, CoreMatchers.equalTo(true));
+        MatcherAssert.assertThat(tv1.compareTo(tv3) == 0, CoreMatchers.equalTo(true));
+        MatcherAssert.assertThat(tv1.compareTo(tv4) == 0, CoreMatchers.equalTo(true));
+        MatcherAssert.assertThat(tv1.compareTo(tv5) < 0, CoreMatchers.equalTo(true));
+        MatcherAssert.assertThat(tv6.compareTo(tv5) == 0, CoreMatchers.equalTo(true));
+        MatcherAssert.assertThat(tv6.compareTo(tv4) > 0, CoreMatchers.equalTo(true));
         try {
             tv1.compareTo(null);
             Assert.fail("NullPointerException expected");
         } catch (final NullPointerException expected) {
+            // TODO Use JUnit 5 assertThrows instead.
         }
     }
 
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/util/TestTimeout.java b/httpcore5/src/test/java/org/apache/hc/core5/util/TestTimeout.java
index 80f92c5..8afdd2a 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/util/TestTimeout.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/util/TestTimeout.java
@@ -28,6 +28,7 @@
 package org.apache.hc.core5.util;
 
 import java.text.ParseException;
+import java.time.Duration;
 import java.util.concurrent.TimeUnit;
 
 import org.junit.Assert;
@@ -101,6 +102,21 @@ public class TestTimeout {
     }
 
     @Test
+    public void testFactoryForDuration() {
+        assertConvertion(Duration.ZERO);
+        assertConvertion(Duration.ofDays(1));
+        assertConvertion(Duration.ofHours(1));
+        assertConvertion(Duration.ofMillis(1));
+        assertConvertion(Duration.ofNanos(1));
+        assertConvertion(Duration.ofSeconds(1));
+        assertConvertion(Duration.ofSeconds(1, 1));
+    }
+
+    private void assertConvertion(final Duration duration) {
+        Assert.assertEquals(duration, Timeout.of(duration).toDuration());
+    }
+
+    @Test
     public void testFactoryForHours() {
         testFactory(TimeUnit.HOURS);
     }