Skip to content

Commit 7e549e2

Browse files
authored
Merge pull request #755 from slok/slok/ui
Support time utils
2 parents 02325ed + 0fce118 commit 7e549e2

File tree

3 files changed

+466
-48
lines changed

3 files changed

+466
-48
lines changed

internal/http/backend/app/time_utils.go

Lines changed: 10 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,12 @@ import (
66
"time"
77

88
"github.com/slok/sloth/internal/http/backend/model"
9+
utilstime "github.com/slok/sloth/pkg/common/utils/time"
910
)
1011

1112
func calculateStepsForTimeRange(from, to time.Time) time.Duration {
1213
const autoSteps = 50
13-
totalDuration := to.Sub(from)
14-
step := totalDuration / time.Duration(autoSteps)
15-
16-
// Round step to minutes.
17-
if step < time.Minute {
18-
step = time.Minute
19-
}
20-
step = (time.Duration(int(step.Minutes())) * time.Minute)
21-
22-
return step
14+
return utilstime.CalculateStepsForTimeRange(from, to, autoSteps)
2315
}
2416

2517
func sanitizeDataPoints(dps []model.DataPoint, from, to time.Time, step time.Duration) []model.DataPoint {
@@ -47,44 +39,16 @@ func sanitizeDataPoints(dps []model.DataPoint, from, to time.Time, step time.Dur
4739
return sanitizedDPs
4840
}
4941

50-
func roundTimeToDay(t time.Time) time.Time {
51-
return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())
52-
}
53-
54-
func weekMonday(t time.Time) time.Time {
55-
diff := time.Duration(t.Weekday() - 1)
56-
if diff < 0 {
57-
diff = 6
58-
}
59-
60-
return roundTimeToDay(t).Add(-1 * diff * 24 * time.Hour) // Remove the diff days until monday.
61-
}
62-
63-
func monthFirst(t time.Time) time.Time {
64-
return time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, t.Location())
65-
}
66-
67-
func quarterFirst(t time.Time) time.Time {
68-
// Gets the first day of the quarter the time is in.
69-
month := ((t.Month()-1)/3)*3 + 1
70-
return time.Date(t.Year(), month, 1, 0, 0, 0, 0, t.Location())
71-
}
72-
73-
func yearFirst(t time.Time) time.Time {
74-
// Gets the first day of the year the time is in.
75-
return time.Date(t.Year(), 1, 1, 0, 0, 0, 0, t.Location())
76-
}
77-
7842
func startOfPeriod(t time.Time, periodType BudgetRangeType) (time.Time, error) {
7943
switch periodType {
8044
case BudgetRangeTypeYearly:
81-
return yearFirst(t), nil
45+
return utilstime.YearFirst(t), nil
8246
case BudgetRangeTypeQuarterly:
83-
return quarterFirst(t), nil
47+
return utilstime.QuarterFirst(t), nil
8448
case BudgetRangeTypeMonthly:
85-
return monthFirst(t), nil
49+
return utilstime.MonthFirst(t), nil
8650
case BudgetRangeTypeWeekly:
87-
return weekMonday(t), nil
51+
return utilstime.WeekMonday(t), nil
8852
}
8953

9054
return time.Time{}, fmt.Errorf("unknown budget range type: %q", periodType)
@@ -93,15 +57,13 @@ func startOfPeriod(t time.Time, periodType BudgetRangeType) (time.Time, error) {
9357
func endOfPeriod(t time.Time, periodType BudgetRangeType) (time.Time, error) {
9458
switch periodType {
9559
case BudgetRangeTypeYearly:
96-
return yearFirst(t).Add(365*24*time.Hour - 1), nil
60+
return utilstime.EndOfYear(t), nil
9761
case BudgetRangeTypeQuarterly:
98-
// TODO: This is a simplification, not all months have 30 days.
99-
return quarterFirst(t).Add(3*30*24*time.Hour - 1), nil
62+
return utilstime.EndOfQuarter(t), nil
10063
case BudgetRangeTypeMonthly:
101-
// TODO: This is a simplification, not all months have 30 days.
102-
return monthFirst(t).Add(30*24*time.Hour - 1), nil
64+
return utilstime.EndOfMonth(t), nil
10365
case BudgetRangeTypeWeekly:
104-
return weekMonday(t).Add(7*24*time.Hour - 1), nil
66+
return utilstime.EndOfWeek(t), nil
10567
}
10668

10769
return time.Time{}, fmt.Errorf("unknown budget range type: %q", periodType)
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package time
2+
3+
import (
4+
"time"
5+
)
6+
7+
// CalculateStepsForTimeRange calculates the step duration for a given time range and number of steps.
8+
func CalculateStepsForTimeRange(from, to time.Time, steps int) time.Duration {
9+
totalDuration := to.Sub(from)
10+
step := totalDuration / time.Duration(steps)
11+
12+
// Round step to minutes.
13+
if step < time.Minute {
14+
step = time.Minute
15+
}
16+
step = (time.Duration(int(step.Minutes())) * time.Minute)
17+
18+
return step
19+
}
20+
21+
// RoundTimeToDay rounds a time to the start of the day (00:00:00).
22+
func RoundTimeToDay(t time.Time) time.Time {
23+
return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())
24+
}
25+
26+
// WeekMonday returns the Monday of the week for the given time.
27+
func WeekMonday(t time.Time) time.Time {
28+
diff := time.Duration(t.Weekday() - 1)
29+
if diff < 0 {
30+
diff = 6
31+
}
32+
33+
return RoundTimeToDay(t).Add(-1 * diff * 24 * time.Hour) // Remove the diff days until monday.
34+
}
35+
36+
// MonthFirst returns the first TS of the month for the given time.
37+
func MonthFirst(t time.Time) time.Time {
38+
return time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, t.Location())
39+
}
40+
41+
// QuarterFirst returns the first TS of the quarter for the given time.
42+
func QuarterFirst(t time.Time) time.Time {
43+
// Gets the first day of the quarter the time is in.
44+
month := ((t.Month()-1)/3)*3 + 1
45+
return time.Date(t.Year(), month, 1, 0, 0, 0, 0, t.Location())
46+
}
47+
48+
// YearFirst returns the first TS of the year for the given time.
49+
func YearFirst(t time.Time) time.Time {
50+
// Gets the first day of the year the time is in.
51+
return time.Date(t.Year(), 1, 1, 0, 0, 0, 0, t.Location())
52+
}
53+
54+
// EndOfWeek returns the last TS of the week for the given time.
55+
func EndOfWeek(t time.Time) time.Time {
56+
return WeekMonday(t).Add(7*24*time.Hour - 1)
57+
}
58+
59+
// EndOfMonth returns the last TS of the month for the given time.
60+
func EndOfMonth(t time.Time) time.Time {
61+
return SetEndOfDay(LastDayOfMonth(t))
62+
}
63+
64+
// EndOfQuarter returns the last TS of the quarter for the given time.
65+
func EndOfQuarter(t time.Time) time.Time {
66+
qf := QuarterFirst(t)
67+
qe := NextMonths(qf, 2) // We are at first month of quarter, add 2 to get to last month.
68+
return SetEndOfDay(LastDayOfMonth(qe))
69+
}
70+
71+
func EndOfYear(t time.Time) time.Time {
72+
nextYear := time.Date(t.Year()+1, 1, 1, 0, 0, 0, 0, t.Location())
73+
return SetEndOfDay(nextYear.Add(-24 * time.Hour))
74+
}
75+
76+
// LastDayOfMonth returns the last day of the month for the given time.
77+
func LastDayOfMonth(t time.Time) time.Time {
78+
year := t.Year()
79+
firstOfNextMonth := time.Date(year, t.Month()+1, 1, 0, 0, 0, 0, t.Location())
80+
lastOfMonth := firstOfNextMonth.Add(-24 * time.Hour)
81+
return lastOfMonth
82+
}
83+
84+
// NextMonths returns the time after adding the specified number of months to the given time.
85+
func NextMonths(t time.Time, months int) time.Time {
86+
year := t.Year()
87+
month := t.Month() + time.Month(months)
88+
if month > 12 {
89+
month = month % 12
90+
year++
91+
}
92+
93+
return time.Date(year, month, t.Day(), t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), t.Location())
94+
}
95+
96+
// SetEndOfDay sets the time to the end of the day (23:59:59.999999999) in a given TS.
97+
func SetEndOfDay(t time.Time) time.Time {
98+
return time.Date(t.Year(), t.Month(), t.Day(), 23, 59, 59, 999999999, t.Location())
99+
}

0 commit comments

Comments
 (0)