ソースを参照

Merge pull request #1794 from saweber/saweber/timeutil-week

add timeutil for week
Sean Holcomb 3 年 前
コミット
0d2cc01f8a
3 ファイル変更46 行追加0 行削除
  1. 18 0
      pkg/kubecost/window.go
  2. 12 0
      pkg/kubecost/window_test.go
  3. 16 0
      pkg/util/timeutil/timeutil.go

+ 18 - 0
pkg/kubecost/window.go

@@ -34,6 +34,10 @@ var (
 // in the given time's timezone.
 // e.g. 2020-01-01T12:37:48-0700, 24h = 2020-01-01T00:00:00-0700
 func RoundBack(t time.Time, resolution time.Duration) time.Time {
+	// if the duration is a week - roll back to the following Sunday
+	if resolution == timeutil.Week {
+		return timeutil.RoundToStartOfWeek(t)
+	}
 	_, offSec := t.Zone()
 	return t.Add(time.Duration(offSec) * time.Second).Truncate(resolution).Add(-time.Duration(offSec) * time.Second)
 }
@@ -42,6 +46,11 @@ func RoundBack(t time.Time, resolution time.Duration) time.Time {
 // in the given time's timezone.
 // e.g. 2020-01-01T12:37:48-0700, 24h = 2020-01-02T00:00:00-0700
 func RoundForward(t time.Time, resolution time.Duration) time.Time {
+	// if the duration is a week - roll forward to the following Sunday
+	if resolution == timeutil.Week {
+		return timeutil.RoundToStartOfFollowingWeek(t)
+	}
+
 	back := RoundBack(t, resolution)
 	if back.Equal(t) {
 		// The given time is exactly a multiple of the given resolution
@@ -233,6 +242,9 @@ func parseWindow(window string, now time.Time) (Window, error) {
 		if match[2] == "d" {
 			dur = 24 * time.Hour
 		}
+		if match[2] == "w" {
+			dur = timeutil.Week
+		}
 
 		num, _ := strconv.ParseInt(match[1], 10, 64)
 
@@ -254,6 +266,9 @@ func parseWindow(window string, now time.Time) (Window, error) {
 		if match[4] == "d" {
 			offUnit = 24 * time.Hour
 		}
+		if match[4] == "w" {
+			offUnit = 24 * timeutil.Week
+		}
 
 		offNum, _ := strconv.ParseInt(match[3], 10, 64)
 
@@ -266,6 +281,9 @@ func parseWindow(window string, now time.Time) (Window, error) {
 		if match[2] == "d" {
 			durUnit = 24 * time.Hour
 		}
+		if match[2] == "w" {
+			durUnit = timeutil.Week
+		}
 
 		durNum, _ := strconv.ParseInt(match[1], 10, 64)
 

+ 12 - 0
pkg/kubecost/window_test.go

@@ -88,6 +88,12 @@ func TestRoundBack(t *testing.T) {
 	if !tb.Equal(time.Date(2020, time.January, 1, 0, 0, 0, 0, time.UTC)) {
 		t.Fatalf("RoundBack: expected 2020-01-01T00:00:00Z; actual %s", tb)
 	}
+
+	to = time.Date(2020, time.January, 1, 23, 59, 0, 0, time.UTC)
+	tb = RoundBack(to, timeutil.Week)
+	if !tb.Equal(time.Date(2019, time.December, 29, 0, 0, 0, 0, time.UTC)) {
+		t.Fatalf("RoundForward: expected 2019-12-29T00:00:00Z; actual %s", tb)
+	}
 }
 
 func TestRoundForward(t *testing.T) {
@@ -165,6 +171,12 @@ func TestRoundForward(t *testing.T) {
 	if !tb.Equal(time.Date(2020, time.January, 2, 0, 0, 0, 0, time.UTC)) {
 		t.Fatalf("RoundForward: expected 2020-01-02T00:00:00Z; actual %s", tb)
 	}
+
+	to = time.Date(2020, time.January, 1, 23, 59, 0, 0, time.UTC)
+	tb = RoundForward(to, timeutil.Week)
+	if !tb.Equal(time.Date(2020, time.January, 5, 0, 0, 0, 0, time.UTC)) {
+		t.Fatalf("RoundForward: expected 2020-01-05T00:00:00Z; actual %s", tb)
+	}
 }
 
 func TestParseWindowUTC(t *testing.T) {

+ 16 - 0
pkg/util/timeutil/timeutil.go

@@ -37,6 +37,8 @@ const (
 
 	// Day expresses 24 hours
 	Day = time.Hour * 24.0
+
+	Week = Day * 7.0
 )
 
 // DurationString converts a duration to a Prometheus-compatible string in
@@ -262,6 +264,20 @@ func FormatDurationStringDaysToHours(param string) (string, error) {
 	return param, nil
 }
 
+// RoundToStartOfWeek creates a new time.Time for the preceding Monday 00:00 UTC
+func RoundToStartOfWeek(t time.Time) time.Time {
+	date := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, time.UTC)
+	daysFromMonday := int(date.Weekday())
+	return date.Add(-1 * time.Duration(daysFromMonday) * Day)
+}
+
+// RoundToStartOfFollowingWeek creates a new time.Time for the following Monday 00:00 UTC
+func RoundToStartOfFollowingWeek(t time.Time) time.Time {
+	date := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, time.UTC)
+	daysFromSunday := 7 - int(date.Weekday())
+	return date.Add(time.Duration(daysFromSunday) * Day)
+}
+
 // JobTicker is a ticker used to synchronize the next run of a repeating
 // process. The designated use-case is for infinitely-looping selects,
 // where a timeout or an exit channel might cancel the process, but otherwise