diff --git a/pkg/components/gtime/gtime.go b/pkg/components/gtime/gtime.go index 444e6cc388e..22e6eefb847 100644 --- a/pkg/components/gtime/gtime.go +++ b/pkg/components/gtime/gtime.go @@ -10,7 +10,7 @@ import ( var dateUnitPattern = regexp.MustCompile(`^(\d+)([dwMy])$`) // 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) { dur, period, err := parse(inp) if err != nil { @@ -22,16 +22,18 @@ func ParseInterval(inp string) (time.Duration, error) { 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 { case "d": - return now.Sub(now.AddDate(0, 0, -num)), nil + return now.AddDate(0, 0, num).Sub(now), nil case "w": - return now.Sub(now.AddDate(0, 0, -num*7)), nil + return now.AddDate(0, 0, num*7).Sub(now), nil case "M": - return now.Sub(now.AddDate(0, -num, 0)), nil + return now.AddDate(0, num, 0).Sub(now), nil 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) diff --git a/pkg/components/gtime/gtime_test.go b/pkg/components/gtime/gtime_test.go index 3b21cc334ce..074ec3d8861 100644 --- a/pkg/components/gtime/gtime_test.go +++ b/pkg/components/gtime/gtime_test.go @@ -10,19 +10,17 @@ import ( ) func TestParseInterval(t *testing.T) { - now := time.Now() - tcs := []struct { inp string duration time.Duration err *regexp.Regexp }{ - {inp: "1d", duration: now.Sub(now.AddDate(0, 0, -1))}, - {inp: "1w", duration: now.Sub(now.AddDate(0, 0, -7))}, - {inp: "2w", duration: now.Sub(now.AddDate(0, 0, -14))}, - {inp: "1M", duration: now.Sub(now.AddDate(0, -1, 0))}, - {inp: "1y", duration: now.Sub(now.AddDate(-1, 0, 0))}, - {inp: "5y", duration: now.Sub(now.AddDate(-5, 0, 0))}, + {inp: "1d", duration: 24 * time.Hour}, + {inp: "1w", duration: 168 * time.Hour}, + {inp: "2w", duration: 2 * 168 * time.Hour}, + {inp: "1M", duration: 744 * time.Hour}, + {inp: "1y", duration: 8760 * time.Hour}, + {inp: "5y", duration: 43824 * time.Hour}, {inp: "invalid-duration", err: regexp.MustCompile(`^time: invalid duration "?invalid-duration"?$`)}, } for i, tc := range tcs {