recur every n months

This commit is contained in:
Erik Winter 2021-02-03 10:25:25 +01:00
parent 9f9934ef97
commit 2ea3639505
4 changed files with 97 additions and 5 deletions

View File

@ -201,6 +201,10 @@ func (d Date) Weekday() time.Weekday {
return d.t.Weekday() return d.t.Weekday()
} }
func (d Date) Day() int {
return d.t.Day()
}
func (d Date) Add(days int) Date { func (d Date) Add(days int) Date {
year, month, day := d.t.Date() year, month, day := d.t.Date()
return NewDate(year, int(month), day+days) return NewDate(year, int(month), day+days)

View File

@ -195,13 +195,13 @@ func TestDateString(t *testing.T) {
}, },
{ {
name: "normal", name: "normal",
date: task.NewDate(2021, 1, 30), date: task.NewDate(2021, 5, 30),
exp: "2021-01-30 (saturday)", exp: "2021-05-30 (sunday)",
}, },
{ {
name: "normalize", name: "normalize",
date: task.NewDate(2021, 1, 32), date: task.NewDate(2021, 5, 32),
exp: "2021-02-01 (monday)", exp: "2021-06-01 (tuesday)",
}, },
} { } {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {

View File

@ -37,6 +37,9 @@ func NewRecurrer(recurStr string) Recurrer {
if recur, ok := ParseEveryNWeeks(start, terms); ok { if recur, ok := ParseEveryNWeeks(start, terms); ok {
return recur return recur
} }
if recur, ok := ParseEveryNMonths(start, terms); ok {
return recur
}
return nil return nil
} }
@ -191,7 +194,7 @@ type EveryNWeeks struct {
// yyyy-mm-dd, every 3 weeks // yyyy-mm-dd, every 3 weeks
func ParseEveryNWeeks(start Date, terms []string) (Recurrer, bool) { func ParseEveryNWeeks(start Date, terms []string) (Recurrer, bool) {
if len(terms) < 1 || len(terms) > 1 { if len(terms) != 1 {
return nil, false return nil, false
} }
@ -225,3 +228,41 @@ func (enw EveryNWeeks) RecursOn(date Date) bool {
func (enw EveryNWeeks) String() string { func (enw EveryNWeeks) String() string {
return fmt.Sprintf("%s, every %d weeks", enw.Start.String(), enw.N) return fmt.Sprintf("%s, every %d weeks", enw.Start.String(), enw.N)
} }
type EveryNMonths struct {
Start Date
N int
}
// yyyy-mm-dd, every 3 months
func ParseEveryNMonths(start Date, terms []string) (Recurrer, bool) {
if len(terms) != 1 {
return nil, false
}
terms = strings.Split(terms[0], " ")
if len(terms) != 3 || terms[0] != "every" || terms[2] != "months" {
return nil, false
}
n, err := strconv.Atoi(terms[1])
if err != nil {
return nil, false
}
return EveryNMonths{
Start: start,
N: n,
}, true
}
func (enm EveryNMonths) RecursOn(date Date) bool {
if enm.Start.After(date) {
return false
}
return enm.Start.Day() == date.Day()
}
func (enm EveryNMonths) String() string {
return fmt.Sprintf("%s, every %d months", enm.Start.String(), enm.N)
}

View File

@ -300,3 +300,50 @@ func TestEveryNWeeks(t *testing.T) {
} }
}) })
} }
func TestEveryNMonths(t *testing.T) {
everyNMonths := task.EveryNMonths{
Start: task.NewDate(2021, 2, 3),
N: 3,
}
everyNMonthsStr := "2021-02-03 (wednesday), every 3 months"
t.Run("parse", func(t *testing.T) {
test.Equals(t, everyNMonths, task.NewRecurrer(everyNMonthsStr))
})
t.Run("string", func(t *testing.T) {
test.Equals(t, everyNMonthsStr, everyNMonths.String())
})
t.Run("recurs on", func(t *testing.T) {
for _, tc := range []struct {
name string
date task.Date
exp bool
}{
{
name: "before start",
date: task.NewDate(2021, 1, 27),
},
{
name: "on start",
date: task.NewDate(2021, 2, 3),
exp: true,
},
{
name: "8 weeks after",
date: task.NewDate(2021, 3, 31),
},
{
name: "one month",
date: task.NewDate(2021, 3, 3),
exp: true,
},
} {
t.Run(tc.name, func(t *testing.T) {
test.Equals(t, tc.exp, everyNMonths.RecursOn(tc.date))
})
}
})
}