Нет описания

remind.go 2.8KB

    package main import ( "fmt" "strconv" "strings" "time" ) func main() { dates := []string{ "today", "tomorrow", "tomorrow at 3am", "in 3 days", "in a month", "in 3 months", "next week", "next month", "in two weeks", "in 3 weeks", "2016-09-28", "3pm", "in 4 days at 10 pm", } for _, d := range dates { fmt.Printf("'%s': ", d) t, err := parseTime(d) if err != nil { fmt.Printf("%s\n", err) } else { fmt.Printf("%s\n", t) } } } func parseTime(s string) (time.Time, error) { var t time.Time now := time.Now().Round(time.Second) parts := strings.Fields(s) // more indicates the parts index where there might be "more" // parsable data more := 0 if len(parts) == 0 { return t, fmt.Errorf("empty date spec") } switch parts[0] { case "today": if len(parts) >= 1 { t = now more = 1 } case "tomorrow": if len(parts) >= 1 { t = now.AddDate(0, 0, 1) more = 1 } case "in": if len(parts) >= 3 { n, err := parseNumber(parts[1]) if err != nil { return t, err } modifier, err := parseModifier(parts[2]) if err != nil { return t, err } t = modifier(n, now) more = 3 } case "next": if len(parts) >= 2 { modifier, err := parseModifier(parts[1]) if err != nil { return t, err } t = modifier(1, now) more = 2 } default: return t, fmt.Errorf("unknown date spec '%s'", s) } if len(parts) == more { return t, nil } return t, fmt.Errorf("unknown date spec '%s' (unexpected)", s) } func parseNumber(n string) (int, error) { switch n { case "a", "an", "one": return 1, nil case "two": return 2, nil case "three": return 3, nil case "four": return 4, nil case "five": return 5, nil case "six": return 6, nil case "seven": return 7, nil case "eight": return 8, nil case "nine": return 9, nil case "ten": return 10, nil default: return strconv.Atoi(n) } } func parseModifier(m string) (func(int, time.Time) time.Time, error) { switch m { case "second", "seconds": return durationModifier(time.Second), nil case "minute", "minutes": return durationModifier(time.Minute), nil case "hour", "hours": return durationModifier(time.Hour), nil case "day", "days": return dateModifier(0, 0, 1), nil case "week", "weeks": return dateModifier(0, 0, 7), nil case "month", "months": return dateModifier(0, 1, 0), nil case "year", "years": return dateModifier(1, 0, 0), nil default: return nil, fmt.Errorf("unknown modifier '%s'", m) } } func durationModifier(d time.Duration) func(int, time.Time) time.Time { return func(n int, t time.Time) time.Time { return t.Add(time.Duration(n) * d) } } func dateModifier(years, months, days int) func(int, time.Time) time.Time { return func(n int, t time.Time) time.Time { return t.AddDate(n*years, n*months, n*days) } }