diff options
| -rw-r--r-- | todolist/date_filter.go | 146 | ||||
| -rw-r--r-- | todolist/date_filter_test.go | 95 | ||||
| -rw-r--r-- | todolist/filter.go | 17 |
3 files changed, 250 insertions, 8 deletions
diff --git a/todolist/date_filter.go b/todolist/date_filter.go new file mode 100644 index 0000000..5e4d391 --- /dev/null +++ b/todolist/date_filter.go @@ -0,0 +1,146 @@ +package todolist + +import ( + "regexp" + "time" + + "github.com/jinzhu/now" +) + +type DateFilter struct { + Todos []Todo +} + +func NewDateFilter(todos []Todo) *DateFilter { + return &DateFilter{Todos: todos} +} + +func (f *DateFilter) FilterDate(input string) []Todo { + r, _ := regexp.Compile(`due .*$`) + match := r.FindString(input) + switch { + case match == "due tod" || match == "due today": + return f.filterToday(now.BeginningOfDay()) + case match == "due tom" || match == "due tomorrow": + return f.filterTomorrow(now.BeginningOfDay()) + case match == "due sun" || match == "due sunday": + return f.filterDay(now.BeginningOfDay(), time.Sunday) + case match == "due mon" || match == "due monday": + return f.filterDay(now.BeginningOfDay(), time.Monday) + case match == "due tue" || match == "due tuesday": + return f.filterDay(now.BeginningOfDay(), time.Tuesday) + case match == "due wed" || match == "due wednesday": + return f.filterDay(now.BeginningOfDay(), time.Wednesday) + case match == "due thu" || match == "due thursday": + return f.filterDay(now.BeginningOfDay(), time.Thursday) + case match == "due fri" || match == "due friday": + return f.filterDay(now.BeginningOfDay(), time.Friday) + case match == "due sat" || match == "due saturday": + return f.filterDay(now.BeginningOfDay(), time.Saturday) + case match == "due this week": + return f.filterThisWeek(now.BeginningOfDay()) + case match == "due next week": + return f.filterNextWeek(now.BeginningOfDay()) + case match == "overdue": + return f.filterOverdue(now.BeginningOfDay()) + } + return f.Todos +} + +func (f *DateFilter) filterToday(pivot time.Time) []Todo { + var ret []Todo + for _, todo := range f.Todos { + if todo.Due == pivot.Format("2006-01-02") { + ret = append(ret, todo) + } + } + return ret +} + +func (f *DateFilter) filterDay(pivot time.Time, day time.Weekday) []Todo { + var ret []Todo + filtered := f.filterThisWeek(pivot) + for _, todo := range filtered { + dueTime, _ := time.Parse("2006-01-02", todo.Due) + if dueTime.Weekday() == day { + ret = append(ret, todo) + } + + } + return ret +} + +func (f *DateFilter) filterTomorrow(pivot time.Time) []Todo { + var ret []Todo + pivot = pivot.AddDate(0, 0, 1) + for _, todo := range f.Todos { + if todo.Due == pivot.Format("2006-01-02") { + ret = append(ret, todo) + } + } + return ret +} + +func (f *DateFilter) filterThisWeek(pivot time.Time) []Todo { + var ret []Todo + + begin := f.findSunday(pivot) + end := begin.AddDate(0, 0, 7) + + for _, todo := range f.Todos { + dueTime, _ := time.Parse("2006-01-02", todo.Due) + if begin.Before(dueTime) && end.After(dueTime) { + ret = append(ret, todo) + } + } + return ret +} + +func (f *DateFilter) filterNextWeek(pivot time.Time) []Todo { + var ret []Todo + + begin := f.findSunday(pivot).AddDate(0, 0, 7) + end := begin.AddDate(0, 0, 7) + + for _, todo := range f.Todos { + dueTime, _ := time.Parse("2006-01-02", todo.Due) + if begin.Before(dueTime) && end.After(dueTime) { + ret = append(ret, todo) + } + } + return ret +} + +func (f *DateFilter) filterOverdue(pivot time.Time) []Todo { + var ret []Todo + + pivotDate := pivot.Format("2006-01-02") + + for _, todo := range f.Todos { + dueTime, _ := time.Parse("2006-01-02", todo.Due) + if dueTime.Before(pivot) && pivotDate != todo.Due { + ret = append(ret, todo) + } + } + return ret +} + +func (f *DateFilter) findSunday(pivot time.Time) time.Time { + switch now.New(pivot).Weekday() { + case time.Sunday: + return pivot + case time.Monday: + return pivot.AddDate(0, 0, -1) + case time.Tuesday: + return pivot.AddDate(0, 0, -2) + case time.Wednesday: + return pivot.AddDate(0, 0, -3) + case time.Thursday: + return pivot.AddDate(0, 0, -4) + case time.Friday: + return pivot.AddDate(0, 0, -5) + case time.Saturday: + return pivot.AddDate(0, 0, -6) + } + return pivot +} diff --git a/todolist/date_filter_test.go b/todolist/date_filter_test.go new file mode 100644 index 0000000..cbcc103 --- /dev/null +++ b/todolist/date_filter_test.go @@ -0,0 +1,95 @@ +package todolist + +import ( + "testing" + "time" + + "github.com/jinzhu/now" + "github.com/stretchr/testify/assert" +) + +func TestFilterToday(t *testing.T) { + assert := assert.New(t) + + var todos []Todo + todayTodo := Todo{Id: 1, Subject: "one", Due: time.Now().Format("2006-01-02")} + tomorrowTodo := Todo{Id: 2, Subject: "two", Due: time.Now().AddDate(0, 0, 1).Format("2006-01-02")} + todos = append(todos, todayTodo) + todos = append(todos, tomorrowTodo) + + filter := NewDateFilter(todos) + filtered := filter.filterToday(time.Now()) + + assert.Equal(1, len(filtered)) + assert.Equal(1, filtered[0].Id) +} + +func TestFilterTomorrow(t *testing.T) { + assert := assert.New(t) + + var todos []Todo + todayTodo := Todo{Id: 1, Subject: "one", Due: time.Now().Format("2006-01-02")} + tomorrowTodo := Todo{Id: 2, Subject: "two", Due: time.Now().AddDate(0, 0, 1).Format("2006-01-02")} + todos = append(todos, todayTodo) + todos = append(todos, tomorrowTodo) + + filter := NewDateFilter(todos) + filtered := filter.filterTomorrow(time.Now()) + + assert.Equal(1, len(filtered)) + assert.Equal(2, filtered[0].Id) +} + +func TestFilterThisWeek(t *testing.T) { + assert := assert.New(t) + + var todos []Todo + lastWeekTodo := Todo{Id: 1, Subject: "two", Due: time.Now().AddDate(0, 0, -7).Format("2006-01-02")} + todayTodo := Todo{Id: 2, Subject: "one", Due: time.Now().Format("2006-01-02")} + nextWeekTodo := Todo{Id: 3, Subject: "two", Due: time.Now().AddDate(0, 0, 8).Format("2006-01-02")} + todos = append(todos, lastWeekTodo) + todos = append(todos, todayTodo) + todos = append(todos, nextWeekTodo) + + filter := NewDateFilter(todos) + filtered := filter.filterThisWeek(time.Now()) + + assert.Equal(1, len(filtered)) + assert.Equal(2, filtered[0].Id) +} + +func TestFilterOverdue(t *testing.T) { + assert := assert.New(t) + + var todos []Todo + lastWeekTodo := Todo{Id: 1, Subject: "one", Due: time.Now().AddDate(0, 0, -7).Format("2006-01-02")} + todayTodo := Todo{Id: 2, Subject: "two", Due: now.BeginningOfDay().Format("2006-01-02")} + tomorrowTodo := Todo{Id: 3, Subject: "three", Due: time.Now().AddDate(0, 0, 1).Format("2006-01-02")} + + todos = append(todos, lastWeekTodo) + todos = append(todos, todayTodo) + todos = append(todos, tomorrowTodo) + + filter := NewDateFilter(todos) + filtered := filter.filterOverdue(now.BeginningOfDay()) + + assert.Equal(1, len(filtered)) + assert.Equal(1, filtered[0].Id) +} + +func TestFilterDay(t *testing.T) { + assert := assert.New(t) + + var todos []Todo + mondayTodo := Todo{Id: 1, Subject: "one", Due: now.Monday().Format("2006-01-02")} + tuesdayTodo := Todo{Id: 2, Subject: "two", Due: now.Monday().AddDate(0, 0, 1).Format("2006-01-02")} + + todos = append(todos, mondayTodo) + todos = append(todos, tuesdayTodo) + + filter := NewDateFilter(todos) + filtered := filter.filterDay(now.BeginningOfDay(), time.Monday) + + assert.Equal(1, len(filtered)) + assert.Equal(1, filtered[0].Id) +} diff --git a/todolist/filter.go b/todolist/filter.go index 39e8fbf..73aa2b4 100644 --- a/todolist/filter.go +++ b/todolist/filter.go @@ -12,14 +12,9 @@ func NewFilter(todos []Todo) *TodoFilter { func (f *TodoFilter) Filter(input string) []Todo { f.Todos = f.filterArchived(input) - - if f.isFilteringByProjects(input) { - f.Todos = f.filterProjects(input) - } - - if f.isFilteringByContexts(input) { - f.Todos = f.filterContexts(input) - } + f.Todos = f.filterProjects(input) + f.Todos = f.filterContexts(input) + f.Todos = NewDateFilter(f.Todos).FilterDate(input) return f.Todos } @@ -44,6 +39,9 @@ func (f *TodoFilter) filterArchived(input string) []Todo { } func (f *TodoFilter) filterProjects(input string) []Todo { + if !f.isFilteringByProjects(input) { + return f.Todos + } parser := &Parser{} projects := parser.Projects(input) var ret []Todo @@ -61,6 +59,9 @@ func (f *TodoFilter) filterProjects(input string) []Todo { } func (f *TodoFilter) filterContexts(input string) []Todo { + if !f.isFilteringByContexts(input) { + return f.Todos + } parser := &Parser{} contexts := parser.Contexts(input) var ret []Todo |
