multiple days in weekly recur
This commit is contained in:
parent
aef4dc1af2
commit
835683e1c8
|
@ -2,6 +2,7 @@ package task
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
@ -17,6 +18,35 @@ func init() {
|
|||
Today = NewDate(year, int(month), day)
|
||||
}
|
||||
|
||||
type Weekdays []time.Weekday
|
||||
|
||||
func (wds Weekdays) Len() int { return len(wds) }
|
||||
func (wds Weekdays) Swap(i, j int) { wds[j], wds[i] = wds[i], wds[j] }
|
||||
func (wds Weekdays) Less(i, j int) bool {
|
||||
if wds[i] == time.Sunday {
|
||||
return false
|
||||
}
|
||||
if wds[j] == time.Sunday {
|
||||
return true
|
||||
}
|
||||
|
||||
return int(wds[i]) < int(wds[j])
|
||||
}
|
||||
|
||||
func (wds Weekdays) Unique() Weekdays {
|
||||
mwds := map[time.Weekday]bool{}
|
||||
for _, wd := range wds {
|
||||
mwds[wd] = true
|
||||
}
|
||||
newWds := Weekdays{}
|
||||
for wd := range mwds {
|
||||
newWds = append(newWds, wd)
|
||||
}
|
||||
sort.Sort(newWds)
|
||||
|
||||
return newWds
|
||||
}
|
||||
|
||||
type Date struct {
|
||||
t time.Time
|
||||
}
|
||||
|
|
|
@ -1,12 +1,79 @@
|
|||
package task_test
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.sr.ht/~ewintr/go-kit/test"
|
||||
"git.sr.ht/~ewintr/gte/internal/task"
|
||||
)
|
||||
|
||||
func TestWeekdaysSort(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
input task.Weekdays
|
||||
exp task.Weekdays
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
},
|
||||
{
|
||||
name: "one",
|
||||
input: task.Weekdays{time.Tuesday},
|
||||
exp: task.Weekdays{time.Tuesday},
|
||||
},
|
||||
{
|
||||
name: "multiple",
|
||||
input: task.Weekdays{time.Wednesday, time.Tuesday, time.Monday},
|
||||
exp: task.Weekdays{time.Monday, time.Tuesday, time.Wednesday},
|
||||
},
|
||||
{
|
||||
name: "sunday is last",
|
||||
input: task.Weekdays{time.Saturday, time.Sunday, time.Monday},
|
||||
exp: task.Weekdays{time.Monday, time.Saturday, time.Sunday},
|
||||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
sort.Sort(tc.input)
|
||||
test.Equals(t, tc.exp, tc.input)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestWeekdaysUnique(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
input task.Weekdays
|
||||
exp task.Weekdays
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
input: task.Weekdays{},
|
||||
exp: task.Weekdays{},
|
||||
},
|
||||
{
|
||||
name: "single",
|
||||
input: task.Weekdays{time.Monday},
|
||||
exp: task.Weekdays{time.Monday},
|
||||
},
|
||||
{
|
||||
name: "no doubles",
|
||||
input: task.Weekdays{time.Monday, time.Tuesday, time.Wednesday},
|
||||
exp: task.Weekdays{time.Monday, time.Tuesday, time.Wednesday},
|
||||
},
|
||||
{
|
||||
name: "doubles",
|
||||
input: task.Weekdays{time.Monday, time.Monday, time.Wednesday, time.Monday},
|
||||
exp: task.Weekdays{time.Monday, time.Wednesday},
|
||||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
test.Equals(t, tc.exp, tc.input.Unique())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewDateFromString(t *testing.T) {
|
||||
task.Today = task.NewDate(2021, 1, 30)
|
||||
for _, tc := range []struct {
|
||||
|
|
|
@ -65,10 +65,10 @@ func (d Daily) String() string {
|
|||
|
||||
type Weekly struct {
|
||||
Start Date
|
||||
Weekday time.Weekday
|
||||
Weekdays Weekdays
|
||||
}
|
||||
|
||||
// yyyy-mm-dd, weekly, wednesday
|
||||
// yyyy-mm-dd, weekly, wednesday & saturday & sunday
|
||||
func ParseWeekly(start Date, terms []string) (Recurrer, bool) {
|
||||
if len(terms) < 2 {
|
||||
return nil, false
|
||||
|
@ -78,14 +78,21 @@ func ParseWeekly(start Date, terms []string) (Recurrer, bool) {
|
|||
return nil, false
|
||||
}
|
||||
|
||||
wd, ok := ParseWeekday(terms[1])
|
||||
wds := Weekdays{}
|
||||
for _, wdStr := range strings.Split(terms[1], "&") {
|
||||
wd, ok := ParseWeekday(wdStr)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
wds = append(wds, wd)
|
||||
}
|
||||
if len(wds) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return Weekly{
|
||||
Start: start,
|
||||
Weekday: wd,
|
||||
Weekdays: wds.Unique(),
|
||||
}, true
|
||||
}
|
||||
|
||||
|
@ -94,11 +101,23 @@ func (w Weekly) RecursOn(date Date) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
return w.Weekday == date.Weekday()
|
||||
for _, wd := range w.Weekdays {
|
||||
if wd == date.Weekday() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (w Weekly) String() string {
|
||||
return fmt.Sprintf("%s, weekly, %s", w.Start.String(), strings.ToLower(w.Weekday.String()))
|
||||
weekdayStrs := []string{}
|
||||
for _, wd := range w.Weekdays {
|
||||
weekdayStrs = append(weekdayStrs, wd.String())
|
||||
}
|
||||
weekdayStr := strings.Join(weekdayStrs, " & ")
|
||||
|
||||
return fmt.Sprintf("%s, weekly, %s", w.Start.String(), strings.ToLower(weekdayStr))
|
||||
}
|
||||
|
||||
type Biweekly struct {
|
||||
|
|
|
@ -50,12 +50,110 @@ func TestDaily(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestParseWeekly(t *testing.T) {
|
||||
start := task.NewDate(2021, 2, 7)
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
input []string
|
||||
expOk bool
|
||||
expWeekly task.Weekly
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
},
|
||||
{
|
||||
name: "wrong type",
|
||||
input: []string{"daily"},
|
||||
},
|
||||
{
|
||||
name: "wrong count",
|
||||
input: []string{"weeekly"},
|
||||
},
|
||||
{
|
||||
name: "unknown day",
|
||||
input: []string{"weekly", "festivus"},
|
||||
},
|
||||
{
|
||||
name: "one day",
|
||||
input: []string{"weekly", "monday"},
|
||||
expOk: true,
|
||||
expWeekly: task.Weekly{
|
||||
Start: start,
|
||||
Weekdays: task.Weekdays{
|
||||
time.Monday,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "multiple days",
|
||||
input: []string{"weekly", "monday & thursday & saturday"},
|
||||
expOk: true,
|
||||
expWeekly: task.Weekly{
|
||||
Start: start,
|
||||
Weekdays: task.Weekdays{
|
||||
time.Monday,
|
||||
time.Thursday,
|
||||
time.Saturday,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "wrong order",
|
||||
input: []string{"weekly", "sunday & thursday & wednesday"},
|
||||
expOk: true,
|
||||
expWeekly: task.Weekly{
|
||||
Start: start,
|
||||
Weekdays: task.Weekdays{
|
||||
time.Wednesday,
|
||||
time.Thursday,
|
||||
time.Sunday,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "doubles",
|
||||
input: []string{"weekly", "sunday & sunday & monday"},
|
||||
expOk: true,
|
||||
expWeekly: task.Weekly{
|
||||
Start: start,
|
||||
Weekdays: task.Weekdays{
|
||||
time.Monday,
|
||||
time.Sunday,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "one unknown",
|
||||
input: []string{"weekly", "sunday & someday"},
|
||||
expOk: true,
|
||||
expWeekly: task.Weekly{
|
||||
Start: start,
|
||||
Weekdays: task.Weekdays{
|
||||
time.Sunday,
|
||||
},
|
||||
},
|
||||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
weekly, ok := task.ParseWeekly(start, tc.input)
|
||||
test.Equals(t, tc.expOk, ok)
|
||||
if tc.expOk {
|
||||
test.Equals(t, tc.expWeekly, weekly)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestWeekly(t *testing.T) {
|
||||
weekly := task.Weekly{
|
||||
Start: task.NewDate(2021, 1, 31), // a sunday
|
||||
Weekday: time.Wednesday,
|
||||
Weekdays: task.Weekdays{
|
||||
time.Monday,
|
||||
time.Wednesday,
|
||||
time.Thursday,
|
||||
},
|
||||
}
|
||||
weeklyStr := "2021-01-31 (sunday), weekly, wednesday"
|
||||
weeklyStr := "2021-01-31 (sunday), weekly, monday & wednesday & thursday"
|
||||
|
||||
t.Run("parse", func(t *testing.T) {
|
||||
test.Equals(t, weekly, task.NewRecurrer(weeklyStr))
|
||||
|
@ -76,14 +174,19 @@ func TestWeekly(t *testing.T) {
|
|||
date: task.NewDate(2021, 1, 27), // a wednesday
|
||||
},
|
||||
{
|
||||
name: "wrong weekday",
|
||||
name: "right weekday",
|
||||
date: task.NewDate(2021, 2, 1), // a monday
|
||||
exp: true,
|
||||
},
|
||||
{
|
||||
name: "right day",
|
||||
name: "another right day",
|
||||
date: task.NewDate(2021, 2, 3), // a wednesday
|
||||
exp: true,
|
||||
},
|
||||
{
|
||||
name: "wrong weekday",
|
||||
date: task.NewDate(2021, 2, 5), // a friday
|
||||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
test.Equals(t, tc.exp, weekly.RecursOn(tc.date))
|
||||
|
|
Loading…
Reference in New Issue