You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2021/03/11 22:42:39 UTC

[httpcomponents-core] 05/06: Let TimeValue/Timeout convert to and from Duration. #263.

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

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

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

    Let TimeValue/Timeout convert to and from Duration. #263.
---
 RELEASE_NOTES.txt                                  | 10 +++
 .../java/org/apache/hc/core5/util/TimeValue.java   | 71 +++++++++++++++++++++-
 .../java/org/apache/hc/core5/util/Timeout.java     | 32 ++++++++++
 .../org/apache/hc/core5/util/TestTimeValue.java    | 42 ++++++++++---
 .../java/org/apache/hc/core5/util/TestTimeout.java | 16 +++++
 5 files changed, 162 insertions(+), 9 deletions(-)

diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt
index 7082de3..966a34c 100644
--- a/RELEASE_NOTES.txt
+++ b/RELEASE_NOTES.txt
@@ -1,3 +1,13 @@
+Release 5.2 ALPHA1
+------------------
+
+This is the first ALPHA release in the 5.2 release series that includes a number of
+new features as well as bug fixes from the stable 5.0.x and 5.1.x branches.
+
+* Let TimeValue/Timeout convert to and from Duration. #263.
+  Contributed by Gary Gregory <garydgregory at gmail.com>
+
+
 Release 5.1
 -----------
 
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 c7b303a..39d1e29 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;
@@ -142,12 +145,42 @@ public class TimeValue implements Comparable<TimeValue> {
      *
      * @param duration the time duration in the given {@code timeUnit}.
      * @param timeUnit the time unit for the given duration.
-     * @return a Timeout
+     * @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}.
+     * @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 +210,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 +394,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 89ee793..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,6 +28,7 @@
 package org.apache.hc.core5.util;
 
 import java.text.ParseException;
+import java.time.Duration;
 import java.util.concurrent.TimeUnit;
 
 import org.hamcrest.CoreMatchers;
@@ -119,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
@@ -127,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);
     }
@@ -254,18 +273,24 @@ 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);
@@ -288,7 +313,7 @@ public class TestTimeValue {
     }
 
     @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);
@@ -307,6 +332,7 @@ public class TestTimeValue {
             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);
     }