aboutsummaryrefslogtreecommitdiffstats
path: root/todolist
diff options
context:
space:
mode:
authorGrant Ammons <gammons@gmail.com>2016-05-03 11:06:26 -0400
committerGrant Ammons <gammons@gmail.com>2016-05-03 11:06:26 -0400
commite104abcb3f13a8d6ee1c071c6aaceb2fbfbef775 (patch)
tree249186c2ffaa9514d7be38bd992c433fd270dfb7 /todolist
parent4808994bf548a384f5c4de99b3e5667382bed936 (diff)
Add date filtering
Diffstat (limited to 'todolist')
-rw-r--r--todolist/date_filter.go146
-rw-r--r--todolist/date_filter_test.go95
-rw-r--r--todolist/filter.go17
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