aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/coveragedb
diff options
context:
space:
mode:
authorTaras Madan <tarasmadan@google.com>2024-08-30 10:28:50 +0200
committerTaras Madan <tarasmadan@google.com>2024-08-30 11:51:11 +0000
commitf885a8ff9168f5e83a85ec9b1b02764e02c0f4e8 (patch)
tree98a8ba6bc4c9029ba934e6d8e1a034e4ad1debc5 /pkg/coveragedb
parent3cb12728f957eec0a79ed1d53e0719fb1a772a6b (diff)
dashboard/app: total coverage is about months or quarters
Total coverage page defaults to quarters (?period=quarter). Monthly data is available with ?period=month.
Diffstat (limited to 'pkg/coveragedb')
-rw-r--r--pkg/coveragedb/time_period.go52
-rw-r--r--pkg/coveragedb/time_period_test.go28
2 files changed, 67 insertions, 13 deletions
diff --git a/pkg/coveragedb/time_period.go b/pkg/coveragedb/time_period.go
index 463ee6c41..b3a2aad73 100644
--- a/pkg/coveragedb/time_period.go
+++ b/pkg/coveragedb/time_period.go
@@ -4,6 +4,8 @@
package coveragedb
import (
+ "errors"
+ "slices"
"sort"
"cloud.google.com/go/civil"
@@ -14,19 +16,59 @@ type TimePeriod struct {
Days int
}
+const (
+ MonthPeriod = "month"
+ QuarterPeriod = "quarter"
+)
+
+var errUnknownTimePeriodType = errors.New("unknown time period type")
+
+func MinMaxDays(periodType string) (int, int, error) {
+ switch periodType {
+ case MonthPeriod:
+ return 28, 31, nil
+ case QuarterPeriod:
+ return 31 + 28 + 31, 31 + 30 + 31, nil
+ default:
+ return 0, 0, errUnknownTimePeriodType
+ }
+}
+
+func PeriodOps(periodType string) (periodOps, error) {
+ switch periodType {
+ case MonthPeriod:
+ return &MonthPeriodOps{}, nil
+ case QuarterPeriod:
+ return &QuarterPeriodOps{}, nil
+ default:
+ return nil, errUnknownTimePeriodType
+ }
+}
+
type periodOps interface {
- isValidPeriod(p TimePeriod) bool
+ IsValidPeriod(p TimePeriod) bool
lastPeriodDate(d civil.Date) civil.Date
pointedPeriodDays(d civil.Date) int
}
+func GenNPeriodEndDatesTill(n int, d civil.Date, po periodOps) []civil.Date {
+ var res []civil.Date
+ for i := 0; i < n; i++ {
+ d = po.lastPeriodDate(d)
+ res = append(res, d)
+ d = d.AddDays(-po.pointedPeriodDays(d))
+ }
+ slices.Reverse(res)
+ return res
+}
+
type DayPeriodOps struct{}
func (dpo *DayPeriodOps) lastPeriodDate(d civil.Date) civil.Date {
return d
}
-func (dpo *DayPeriodOps) isValidPeriod(p TimePeriod) bool {
+func (dpo *DayPeriodOps) IsValidPeriod(p TimePeriod) bool {
return p.Days == 1
}
@@ -43,7 +85,7 @@ func (m *MonthPeriodOps) lastPeriodDate(d civil.Date) civil.Date {
return d.AddDays(-1)
}
-func (m *MonthPeriodOps) isValidPeriod(p TimePeriod) bool {
+func (m *MonthPeriodOps) IsValidPeriod(p TimePeriod) bool {
lmd := m.lastPeriodDate(p.DateTo)
return lmd == p.DateTo && p.Days == lmd.Day
}
@@ -54,7 +96,7 @@ func (m *MonthPeriodOps) pointedPeriodDays(d civil.Date) int {
type QuarterPeriodOps struct{}
-func (q *QuarterPeriodOps) isValidPeriod(p TimePeriod) bool {
+func (q *QuarterPeriodOps) IsValidPeriod(p TimePeriod) bool {
lmd := q.lastPeriodDate(p.DateTo)
return lmd == p.DateTo && p.Days == q.pointedPeriodDays(lmd)
}
@@ -83,7 +125,7 @@ func PeriodsToMerge(srcDates, mergedPeriods []TimePeriod, srcRows, mergedRows []
periodRows[periodID] += srcRows[i]
}
for i, period := range mergedPeriods {
- if !ops.isValidPeriod(period) {
+ if !ops.IsValidPeriod(period) {
continue
}
mergerPeriodID := period.DateTo
diff --git a/pkg/coveragedb/time_period_test.go b/pkg/coveragedb/time_period_test.go
index 85fb4b407..86201e4db 100644
--- a/pkg/coveragedb/time_period_test.go
+++ b/pkg/coveragedb/time_period_test.go
@@ -19,10 +19,14 @@ func TestDayPeriodOps(t *testing.T) {
assert.Equal(t, "2024-02-20", ops.lastPeriodDate(d).String())
- assert.True(t, ops.isValidPeriod(goodPeriod))
- assert.False(t, ops.isValidPeriod(badPeriod))
+ assert.True(t, ops.IsValidPeriod(goodPeriod))
+ assert.False(t, ops.IsValidPeriod(badPeriod))
assert.Equal(t, 1, ops.pointedPeriodDays(d))
+
+ assert.Equal(t,
+ []civil.Date{{Year: 2024, Month: time.February, Day: 19}, {Year: 2024, Month: time.February, Day: 20}},
+ GenNPeriodEndDatesTill(2, d, ops))
}
func TestMonthPeriodOps(t *testing.T) {
@@ -37,11 +41,15 @@ func TestMonthPeriodOps(t *testing.T) {
assert.Equal(t, "2024-02-29", ops.lastPeriodDate(midMonthDate).String())
- assert.True(t, ops.isValidPeriod(goodPeriod))
- assert.False(t, ops.isValidPeriod(badPeriod1))
- assert.False(t, ops.isValidPeriod(badPeriod2))
+ assert.True(t, ops.IsValidPeriod(goodPeriod))
+ assert.False(t, ops.IsValidPeriod(badPeriod1))
+ assert.False(t, ops.IsValidPeriod(badPeriod2))
assert.Equal(t, 29, ops.pointedPeriodDays(midMonthDate))
+
+ assert.Equal(t,
+ []civil.Date{{Year: 2024, Month: time.January, Day: 31}, {Year: 2024, Month: time.February, Day: 29}},
+ GenNPeriodEndDatesTill(2, goodPeriod.DateTo, ops))
}
func TestQuarterPeriodOps(t *testing.T) {
@@ -57,11 +65,15 @@ func TestQuarterPeriodOps(t *testing.T) {
assert.Equal(t, "2024-03-31", ops.lastPeriodDate(midQuarterDate).String())
- assert.True(t, ops.isValidPeriod(goodPeriod))
- assert.False(t, ops.isValidPeriod(badPeriod1))
- assert.False(t, ops.isValidPeriod(badPeriod2))
+ assert.True(t, ops.IsValidPeriod(goodPeriod))
+ assert.False(t, ops.IsValidPeriod(badPeriod1))
+ assert.False(t, ops.IsValidPeriod(badPeriod2))
assert.Equal(t, 31+29+31, ops.pointedPeriodDays(midQuarterDate))
+
+ assert.Equal(t,
+ []civil.Date{{Year: 2023, Month: time.December, Day: 31}, {Year: 2024, Month: time.March, Day: 31}},
+ GenNPeriodEndDatesTill(2, goodPeriod.DateTo, ops))
}
func TestPeriodsToMerge(t *testing.T) {