]> Cypherpunks repositories - gostls13.git/commitdiff
time: add Duration.Truncate and Duration.Round
authorCaleb Spare <cespare@gmail.com>
Thu, 9 Feb 2017 03:47:23 +0000 (19:47 -0800)
committerRuss Cox <rsc@golang.org>
Tue, 14 Feb 2017 00:40:31 +0000 (00:40 +0000)
Fixes #18996

Change-Id: I0b0f7270960b368ce97ad4456f60bcc1fc2a8313
Reviewed-on: https://go-review.googlesource.com/36615
Run-TryBot: Caleb Spare <cespare@gmail.com>
Reviewed-by: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/time/time.go
src/time/time_test.go

index bbe650a9b4253547338395011bcfa2cb167740d6..48aa1eb8f23741b615c37434262819554feca518 100644 (file)
@@ -783,6 +783,45 @@ func (d Duration) Hours() float64 {
        return float64(hour) + float64(nsec)/(60*60*1e9)
 }
 
+// Truncate returns the result of rounding d toward zero to a multiple of m.
+// If m <= 0, Truncate returns d unchanged.
+func (d Duration) Truncate(m Duration) Duration {
+       if m <= 0 {
+               return d
+       }
+       return d - d%m
+}
+
+// Round returns the result of rounding d to the nearest multiple of m.
+// The rounding behavior for halfway values is to round away from zero.
+// If the result exceeds the maximum (or minimum)
+// value that can be stored in a Duration,
+// Round returns the maximum (or minimum) duration.
+// If m <= 0, Round returns d unchanged.
+func (d Duration) Round(m Duration) Duration {
+       if m <= 0 {
+               return d
+       }
+       r := d % m
+       if d < 0 {
+               r = -r
+               if r+r < m {
+                       return d + r
+               }
+               if d1 := d - m + r; d1 < d {
+                       return d1
+               }
+               return minDuration // overflow
+       }
+       if r+r < m {
+               return d - r
+       }
+       if d1 := d + m - r; d1 > d {
+               return d1
+       }
+       return maxDuration // overflow
+}
+
 // Add returns the time t+d.
 func (t Time) Add(d Duration) Time {
        dsec := int64(d / 1e9)
index 90e2abf03efdb6b49ce885def816f379e5536a64..ebe28e61f4ea6dfd57f4e918732178c1cc3feb7f 100644 (file)
@@ -1058,6 +1058,65 @@ func TestDurationHours(t *testing.T) {
        }
 }
 
+var durationTruncateTests = []struct {
+       d    Duration
+       m    Duration
+       want Duration
+}{
+       {0, Second, 0},
+       {Minute, -7 * Second, Minute},
+       {Minute, 0, Minute},
+       {Minute, 1, Minute},
+       {Minute + 10*Second, 10 * Second, Minute + 10*Second},
+       {2*Minute + 10*Second, Minute, 2 * Minute},
+       {10*Minute + 10*Second, 3 * Minute, 9 * Minute},
+       {Minute + 10*Second, Minute + 10*Second + 1, 0},
+       {Minute + 10*Second, Hour, 0},
+       {-Minute, Second, -Minute},
+       {-10 * Minute, 3 * Minute, -9 * Minute},
+       {-10 * Minute, Hour, 0},
+}
+
+func TestDurationTruncate(t *testing.T) {
+       for _, tt := range durationTruncateTests {
+               if got := tt.d.Truncate(tt.m); got != tt.want {
+                       t.Errorf("Duration(%s).Truncate(%s) = %s; want: %s", tt.d, tt.m, got, tt.want)
+               }
+       }
+}
+
+var durationRoundTests = []struct {
+       d    Duration
+       m    Duration
+       want Duration
+}{
+       {0, Second, 0},
+       {Minute, -11 * Second, Minute},
+       {Minute, 0, Minute},
+       {Minute, 1, Minute},
+       {2 * Minute, Minute, 2 * Minute},
+       {2*Minute + 10*Second, Minute, 2 * Minute},
+       {2*Minute + 30*Second, Minute, 3 * Minute},
+       {2*Minute + 50*Second, Minute, 3 * Minute},
+       {-Minute, 1, -Minute},
+       {-2 * Minute, Minute, -2 * Minute},
+       {-2*Minute - 10*Second, Minute, -2 * Minute},
+       {-2*Minute - 30*Second, Minute, -3 * Minute},
+       {-2*Minute - 50*Second, Minute, -3 * Minute},
+       {8e18, 3e18, 9e18},
+       {9e18, 5e18, 1<<63 - 1},
+       {-8e18, 3e18, -9e18},
+       {-9e18, 5e18, -1 << 63},
+}
+
+func TestDurationRound(t *testing.T) {
+       for _, tt := range durationRoundTests {
+               if got := tt.d.Round(tt.m); got != tt.want {
+                       t.Errorf("Duration(%s).Round(%s) = %s; want: %s", tt.d, tt.m, got, tt.want)
+               }
+       }
+}
+
 var defaultLocTests = []struct {
        name string
        f    func(t1, t2 Time) bool