Skip to content

Commit

Permalink
Merge pull request #52155 from otan-cockroach/backport19.2-52138
Browse files Browse the repository at this point in the history
release-19.2: duration: fix negative duration math
  • Loading branch information
otan authored Aug 3, 2020
2 parents 1aed8c2 + 986b48c commit b0a0b8b
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 5 deletions.
7 changes: 6 additions & 1 deletion pkg/util/duration/duration.go
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,12 @@ func Add(ctx Context, t time.Time, d Duration) time.Time {
}

// Adjustments for 1-based math.
expectedMonth := time.Month((int(t.Month())-1+int(d.Months))%12 + 1)
expectedMonth := time.Month((int(t.Month())-1+int(d.Months))%12) + 1
// If we have a negative duration, we have a negative modulus.
// Push it back up to the positive expectedMonth.
if expectedMonth <= 0 {
expectedMonth += 12
}

// Use AddDate() to get a rough value. This might overshoot the
// end of the expected month by multiple days. We could iteratively
Expand Down
101 changes: 97 additions & 4 deletions pkg/util/duration/duration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
package duration

import (
"fmt"
"math"
"testing"
"time"
Expand Down Expand Up @@ -212,6 +213,56 @@ func TestAdd(t *testing.T) {
d: Duration{Months: 15},
exp: time.Date(1994, 1, 01, 0, 0, 0, 0, time.UTC),
},
{
t: time.Date(2020, time.July, 28, 0, 0, 0, 0, time.UTC),
d: Duration{Months: 12},
exp: time.Date(2021, time.July, 28, 0, 0, 0, 0, time.UTC),
},
{
t: time.Date(2020, time.July, 29, 0, 0, 0, 0, time.UTC),
d: Duration{Months: 18},
exp: time.Date(2022, time.January, 29, 0, 0, 0, 0, time.UTC),
},
{
t: time.Date(2020, time.July, 29, 0, 0, 0, 0, time.UTC),
d: Duration{Months: 30},
exp: time.Date(2023, time.January, 29, 0, 0, 0, 0, time.UTC),
},
{
t: time.Date(2020, time.July, 29, 0, 0, 0, 0, time.UTC),
d: Duration{Months: 12},
exp: time.Date(2021, time.July, 29, 0, 0, 0, 0, time.UTC),
},
{
t: time.Date(2020, time.July, 29, 0, 0, 0, 0, time.UTC),
d: Duration{Months: 12, nanos: int64(10 * time.Second)},
exp: time.Date(2021, time.July, 29, 0, 0, 10, 0, time.UTC),
},
{
t: time.Date(2020, time.July, 29, 0, 0, 0, 0, time.UTC),
d: Duration{Months: 17, nanos: int64(10 * time.Second)},
exp: time.Date(2021, time.December, 29, 0, 0, 10, 0, time.UTC),
},
{
t: time.Date(2020, time.July, 29, 0, 0, 0, 0, time.UTC),
d: Duration{Months: 18, nanos: int64(10 * time.Second)},
exp: time.Date(2022, time.January, 29, 0, 0, 10, 0, time.UTC),
},
{
t: time.Date(2020, time.July, 29, 0, 0, 0, 0, time.UTC),
d: Duration{Months: 19, nanos: int64(10 * time.Second)},
exp: time.Date(2022, time.February, 28, 0, 0, 10, 0, time.UTC),
},
{
t: time.Date(2020, time.July, 29, 0, 0, 0, 0, time.UTC),
d: Duration{Months: 20, nanos: int64(10 * time.Second)},
exp: time.Date(2022, time.March, 29, 0, 0, 10, 0, time.UTC),
},
{
t: time.Date(2020, time.July, 30, 0, 0, 0, 0, time.UTC),
d: Duration{Months: 12},
exp: time.Date(2021, time.July, 30, 0, 0, 0, 0, time.UTC),
},

// Check leap behaviors
{
Expand Down Expand Up @@ -270,12 +321,54 @@ func TestAdd(t *testing.T) {
d: Duration{Months: -1, Days: -1},
exp: time.Date(2015, 12, 31, 0, 0, 0, 0, time.UTC),
},
{
t: time.Date(2020, time.July, 28, 0, 0, 0, 0, time.UTC),
d: Duration{Months: -12},
exp: time.Date(2019, time.July, 28, 0, 0, 0, 0, time.UTC),
},
{
t: time.Date(2020, time.July, 29, 0, 0, 0, 0, time.UTC),
d: Duration{Months: -18},
exp: time.Date(2019, time.January, 29, 0, 0, 0, 0, time.UTC),
},
{
t: time.Date(2020, time.July, 29, 0, 0, 0, 0, time.UTC),
d: Duration{Months: -30},
exp: time.Date(2018, time.January, 29, 0, 0, 0, 0, time.UTC),
},
{
t: time.Date(2020, time.July, 29, 0, 0, 0, 0, time.UTC),
d: Duration{Months: -12},
exp: time.Date(2019, time.July, 29, 0, 0, 0, 0, time.UTC),
},
{
t: time.Date(2020, time.July, 29, 0, 0, 0, 0, time.UTC),
d: Duration{Months: -12, nanos: int64(-10 * time.Second)},
exp: time.Date(2019, time.July, 28, 23, 59, 50, 0, time.UTC),
},
{
t: time.Date(2020, time.July, 29, 0, 0, 0, 0, time.UTC),
d: Duration{Months: -19, nanos: int64(-10 * time.Second)},
exp: time.Date(2018, time.December, 28, 23, 59, 50, 0, time.UTC),
},
{
t: time.Date(2020, time.July, 29, 0, 0, 0, 0, time.UTC),
d: Duration{Months: -20, nanos: int64(-10 * time.Second)},
exp: time.Date(2018, time.November, 28, 23, 59, 50, 0, time.UTC),
},
{
t: time.Date(2020, time.July, 30, 0, 0, 0, 0, time.UTC),
d: Duration{Months: -12},
exp: time.Date(2019, time.July, 30, 0, 0, 0, 0, time.UTC),
},
}
for i, test := range tests {
if res := Add(nil, test.t, test.d); !test.exp.Equal(res) {
t.Errorf("%d: expected Add(%v, %d) = %v, found %v",
i, test.t, test.d, test.exp, res)
}
t.Run(fmt.Sprintf("%s_%s", test.t, test.d), func(t *testing.T) {
if res := Add(nil, test.t, test.d); !test.exp.Equal(res) {
t.Errorf("%d: expected Add(%s, %s) = %s, found %s",
i, test.t, test.d, test.exp, res)
}
})
}
}

Expand Down

0 comments on commit b0a0b8b

Please sign in to comment.