gtime: Make ParseInterval deterministic (#32539)

* gtime: Make ParseInterval deterministic by using UTC timezone

Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>
This commit is contained in:
Arve Knudsen 2021-03-31 16:44:23 +02:00 committed by GitHub
parent aad43869c3
commit 6730558f8c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 14 additions and 14 deletions

View File

@ -10,7 +10,7 @@ import (
var dateUnitPattern = regexp.MustCompile(`^(\d+)([dwMy])$`) var dateUnitPattern = regexp.MustCompile(`^(\d+)([dwMy])$`)
// ParseInterval parses an interval with support for all units that Grafana uses. // ParseInterval parses an interval with support for all units that Grafana uses.
// An interval is relative the current wall time. // An interval is relative to the current wall time.
func ParseInterval(inp string) (time.Duration, error) { func ParseInterval(inp string) (time.Duration, error) {
dur, period, err := parse(inp) dur, period, err := parse(inp)
if err != nil { if err != nil {
@ -22,16 +22,18 @@ func ParseInterval(inp string) (time.Duration, error) {
num := int(dur) num := int(dur)
now := time.Now() // Use UTC to ensure that the interval is deterministic, and daylight saving
// doesn't cause surprises
now := time.Now().UTC()
switch period { switch period {
case "d": case "d":
return now.Sub(now.AddDate(0, 0, -num)), nil return now.AddDate(0, 0, num).Sub(now), nil
case "w": case "w":
return now.Sub(now.AddDate(0, 0, -num*7)), nil return now.AddDate(0, 0, num*7).Sub(now), nil
case "M": case "M":
return now.Sub(now.AddDate(0, -num, 0)), nil return now.AddDate(0, num, 0).Sub(now), nil
case "y": case "y":
return now.Sub(now.AddDate(-num, 0, 0)), nil return now.AddDate(num, 0, 0).Sub(now), nil
} }
return 0, fmt.Errorf("invalid interval %q", inp) return 0, fmt.Errorf("invalid interval %q", inp)

View File

@ -10,19 +10,17 @@ import (
) )
func TestParseInterval(t *testing.T) { func TestParseInterval(t *testing.T) {
now := time.Now()
tcs := []struct { tcs := []struct {
inp string inp string
duration time.Duration duration time.Duration
err *regexp.Regexp err *regexp.Regexp
}{ }{
{inp: "1d", duration: now.Sub(now.AddDate(0, 0, -1))}, {inp: "1d", duration: 24 * time.Hour},
{inp: "1w", duration: now.Sub(now.AddDate(0, 0, -7))}, {inp: "1w", duration: 168 * time.Hour},
{inp: "2w", duration: now.Sub(now.AddDate(0, 0, -14))}, {inp: "2w", duration: 2 * 168 * time.Hour},
{inp: "1M", duration: now.Sub(now.AddDate(0, -1, 0))}, {inp: "1M", duration: 744 * time.Hour},
{inp: "1y", duration: now.Sub(now.AddDate(-1, 0, 0))}, {inp: "1y", duration: 8760 * time.Hour},
{inp: "5y", duration: now.Sub(now.AddDate(-5, 0, 0))}, {inp: "5y", duration: 43824 * time.Hour},
{inp: "invalid-duration", err: regexp.MustCompile(`^time: invalid duration "?invalid-duration"?$`)}, {inp: "invalid-duration", err: regexp.MustCompile(`^time: invalid duration "?invalid-duration"?$`)},
} }
for i, tc := range tcs { for i, tc := range tcs {