2021-01-23 12:26:26 +01:00
|
|
|
package task
|
|
|
|
|
2021-01-31 10:01:03 +01:00
|
|
|
import (
|
2021-01-31 12:11:02 +01:00
|
|
|
"fmt"
|
2021-01-31 10:01:03 +01:00
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
)
|
2021-01-23 13:43:28 +01:00
|
|
|
|
2021-01-23 12:26:26 +01:00
|
|
|
type Recurrer interface {
|
2021-01-31 10:01:03 +01:00
|
|
|
RecursOn(date Date) bool
|
|
|
|
String() string
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewRecurrer(recurStr string) Recurrer {
|
|
|
|
terms := strings.Split(recurStr, ", ")
|
2021-01-31 12:11:02 +01:00
|
|
|
if len(terms) < 2 {
|
2021-01-31 10:01:03 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-01-31 12:11:02 +01:00
|
|
|
start := NewDateFromString(terms[0])
|
|
|
|
if start.IsZero() {
|
2021-01-31 10:01:03 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-01-31 12:11:02 +01:00
|
|
|
terms = terms[1:]
|
|
|
|
|
|
|
|
if recur, ok := ParseDaily(start, terms); ok {
|
|
|
|
return recur
|
|
|
|
}
|
|
|
|
if recur, ok := ParseWeekly(start, terms); ok {
|
|
|
|
return recur
|
|
|
|
}
|
|
|
|
if recur, ok := ParseBiweekly(start, terms); ok {
|
|
|
|
return recur
|
2021-01-31 10:01:03 +01:00
|
|
|
}
|
|
|
|
|
2021-01-31 12:11:02 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type Daily struct {
|
|
|
|
Start Date
|
|
|
|
}
|
|
|
|
|
|
|
|
func ParseDaily(start Date, terms []string) (Recurrer, bool) {
|
|
|
|
if len(terms) < 1 {
|
|
|
|
return nil, false
|
2021-01-31 10:01:03 +01:00
|
|
|
}
|
|
|
|
|
2021-01-31 12:11:02 +01:00
|
|
|
if terms[0] != "daily" {
|
|
|
|
return nil, false
|
2021-01-31 10:01:03 +01:00
|
|
|
}
|
2021-01-31 12:11:02 +01:00
|
|
|
|
|
|
|
return Daily{
|
|
|
|
Start: start,
|
|
|
|
}, true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d Daily) RecursOn(date Date) bool {
|
|
|
|
return date.Equal(d.Start) || date.After(d.Start)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d Daily) String() string {
|
|
|
|
return fmt.Sprintf("%s, daily", d.Start.String())
|
2021-01-23 12:26:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
type Weekly struct {
|
|
|
|
Start Date
|
2021-01-31 10:01:03 +01:00
|
|
|
Weekday time.Weekday
|
|
|
|
}
|
|
|
|
|
2021-01-31 12:11:02 +01:00
|
|
|
// yyyy-mm-dd, weekly, wednesday
|
|
|
|
func ParseWeekly(start Date, terms []string) (Recurrer, bool) {
|
|
|
|
if len(terms) < 2 {
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
|
|
|
|
if terms[0] != "weekly" {
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
|
|
|
|
wd, ok := ParseWeekday(terms[1])
|
|
|
|
if !ok {
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
|
|
|
|
return Weekly{
|
|
|
|
Start: start,
|
|
|
|
Weekday: wd,
|
|
|
|
}, true
|
|
|
|
}
|
|
|
|
|
2021-01-31 10:01:03 +01:00
|
|
|
func (w Weekly) RecursOn(date Date) bool {
|
2021-01-31 12:11:02 +01:00
|
|
|
if w.Start.After(date) {
|
2021-01-31 10:01:03 +01:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
return w.Weekday == date.Weekday()
|
2021-01-23 12:26:26 +01:00
|
|
|
}
|
|
|
|
|
2021-01-31 12:11:02 +01:00
|
|
|
func (w Weekly) String() string {
|
|
|
|
return fmt.Sprintf("%s, weekly, %s", w.Start.String(), strings.ToLower(w.Weekday.String()))
|
|
|
|
}
|
2021-01-23 13:43:28 +01:00
|
|
|
|
2021-01-31 12:11:02 +01:00
|
|
|
type Biweekly struct {
|
|
|
|
Start Date
|
|
|
|
Weekday time.Weekday
|
2021-01-23 12:26:26 +01:00
|
|
|
}
|
|
|
|
|
2021-01-31 12:11:02 +01:00
|
|
|
// yyyy-mm-dd, biweekly, wednesday
|
|
|
|
func ParseBiweekly(start Date, terms []string) (Recurrer, bool) {
|
|
|
|
if len(terms) < 2 {
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
|
|
|
|
if terms[0] != "biweekly" {
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
|
|
|
|
wd, ok := ParseWeekday(terms[1])
|
|
|
|
if !ok {
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
|
|
|
|
return Biweekly{
|
|
|
|
Start: start,
|
|
|
|
Weekday: wd,
|
|
|
|
}, true
|
2021-01-31 10:01:03 +01:00
|
|
|
}
|
|
|
|
|
2021-01-31 12:11:02 +01:00
|
|
|
func (b Biweekly) RecursOn(date Date) bool {
|
|
|
|
if b.Start.After(date) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
if b.Weekday != date.Weekday() {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// find first
|
|
|
|
tDate := b.Start
|
|
|
|
for {
|
|
|
|
if tDate.Weekday() == b.Weekday {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
tDate = tDate.AddDays(1)
|
|
|
|
}
|
|
|
|
|
|
|
|
// add weeks
|
|
|
|
for {
|
|
|
|
switch {
|
|
|
|
case tDate.Equal(date):
|
|
|
|
return true
|
|
|
|
case tDate.After(date):
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
tDate = tDate.AddDays(14)
|
|
|
|
}
|
2021-01-23 12:26:26 +01:00
|
|
|
}
|
|
|
|
|
2021-01-31 12:11:02 +01:00
|
|
|
func (b Biweekly) String() string {
|
|
|
|
return fmt.Sprintf("%s, biweekly, %s", b.Start.String(), strings.ToLower(b.Weekday.String()))
|
2021-01-23 12:26:26 +01:00
|
|
|
}
|