From 751720c04d9fe7a2e2424d0c197b48c5019e0954 Mon Sep 17 00:00:00 2001 From: upstream Date: Fri, 2 Oct 2026 16:04:11 +0200 Subject: [PATCH] Upstream olebedev/when state of the touched files before 8381199380 --- rules/en/deadline.go | 107 ++++++++++++++++++++++++++++++++++++++ rules/en/deadline_test.go | 33 ++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 rules/en/deadline.go create mode 100644 rules/en/deadline_test.go diff --git a/rules/en/deadline.go b/rules/en/deadline.go new file mode 100644 index 0000000..2996586 --- /dev/null +++ b/rules/en/deadline.go @@ -0,0 +1,107 @@ +package en + +import ( + "regexp" + "strconv" + "strings" + "time" + + "github.com/AlekSi/pointer" + "github.com/olebedev/when/rules" + "github.com/pkg/errors" +) + +func Deadline(s rules.Strategy) rules.Rule { + overwrite := s == rules.Override + + return &rules.F{ + RegExp: regexp.MustCompile( + "(?i)(?:\\W|^)(within|in)\\s*" + + "(" + INTEGER_WORDS_PATTERN + "|[0-9]+|an?(?:\\s*few)?|half(?:\\s*an?)?)\\s*" + + "(seconds?|min(?:ute)?s?|hours?|days?|weeks?|months?|years?)\\s*" + + "(?:\\W|$)"), + Applier: func(m *rules.Match, c *rules.Context, o *rules.Options, ref time.Time) (bool, error) { + + numStr := strings.TrimSpace(m.Captures[1]) + + var num int + var err error + + if n, ok := INTEGER_WORDS[numStr]; ok { + num = n + } else if numStr == "a" || numStr == "an" { + num = 1 + } else if strings.Contains(numStr, "few") { + num = 3 + } else if strings.Contains(numStr, "half") { + // pass + } else { + num, err = strconv.Atoi(numStr) + if err != nil { + return false, errors.Wrapf(err, "convert '%s' to int", numStr) + } + } + + exponent := strings.TrimSpace(m.Captures[2]) + + if !strings.Contains(numStr, "half") { + switch { + case strings.Contains(exponent, "second"): + if c.Duration == 0 || overwrite { + c.Duration = time.Duration(num) * time.Second + } + case strings.Contains(exponent, "min"): + if c.Duration == 0 || overwrite { + c.Duration = time.Duration(num) * time.Minute + } + case strings.Contains(exponent, "hour"): + if c.Duration == 0 || overwrite { + c.Duration = time.Duration(num) * time.Hour + } + case strings.Contains(exponent, "day"): + if c.Duration == 0 || overwrite { + c.Duration = time.Duration(num) * 24 * time.Hour + } + case strings.Contains(exponent, "week"): + if c.Duration == 0 || overwrite { + c.Duration = time.Duration(num) * 7 * 24 * time.Hour + } + case strings.Contains(exponent, "month"): + if c.Month == nil || overwrite { + c.Month = pointer.ToInt((int(ref.Month()) + num) % 12) + } + case strings.Contains(exponent, "year"): + if c.Year == nil || overwrite { + c.Year = pointer.ToInt(ref.Year() + num) + } + } + } else { + switch { + case strings.Contains(exponent, "hour"): + if c.Duration == 0 || overwrite { + c.Duration = 30 * time.Minute + } + case strings.Contains(exponent, "day"): + if c.Duration == 0 || overwrite { + c.Duration = 12 * time.Hour + } + case strings.Contains(exponent, "week"): + if c.Duration == 0 || overwrite { + c.Duration = 7 * 12 * time.Hour + } + case strings.Contains(exponent, "month"): + if c.Duration == 0 || overwrite { + // 2 weeks + c.Duration = 14 * 24 * time.Hour + } + case strings.Contains(exponent, "year"): + if c.Month == nil || overwrite { + c.Month = pointer.ToInt((int(ref.Month()) + 6) % 12) + } + } + } + + return true, nil + }, + } +} diff --git a/rules/en/deadline_test.go b/rules/en/deadline_test.go new file mode 100644 index 0000000..bebb883 --- /dev/null +++ b/rules/en/deadline_test.go @@ -0,0 +1,33 @@ +package en_test + +import ( + "testing" + "time" + + "github.com/olebedev/when" + "github.com/olebedev/when/rules" + "github.com/olebedev/when/rules/en" +) + +func TestDeadline(t *testing.T) { + fixt := []Fixture{ + {"within half an hour", 0, "within half an hour", time.Hour / 2}, + {"within 1 hour", 0, "within 1 hour", time.Hour}, + {"in 5 minutes", 0, "in 5 minutes", time.Minute * 5}, + {"In 5 minutes I will go home", 0, "In 5 minutes", time.Minute * 5}, + {"we have to do something within 10 days.", 24, "within 10 days", 10 * 24 * time.Hour}, + {"we have to do something in five days.", 24, "in five days", 5 * 24 * time.Hour}, + {"we have to do something in 5 days.", 24, "in 5 days", 5 * 24 * time.Hour}, + {"In 5 seconds A car need to move", 0, "In 5 seconds", 5 * time.Second}, + {"within two weeks", 0, "within two weeks", 14 * 24 * time.Hour}, + {"within a month", 0, "within a month", 31 * 24 * time.Hour}, + {"within a few months", 0, "within a few months", 91 * 24 * time.Hour}, + {"within one year", 0, "within one year", 366 * 24 * time.Hour}, + {"in a week", 0, "in a week", 7 * 24 * time.Hour}, + } + + w := when.New(nil) + w.Add(en.Deadline(rules.Skip)) + + ApplyFixtures(t, "en.Deadline", w, fixt) +}