diff --git a/internal/quickadd/quickadd.go b/internal/quickadd/quickadd.go index 6c18b2d..3d8a3eb 100644 --- a/internal/quickadd/quickadd.go +++ b/internal/quickadd/quickadd.go @@ -650,8 +650,18 @@ func pad2(n int) string { // The trailing group is bounded rather than greedy: without a limit, "hver mandag // kl 10 p1" would hand the whole tail to the recurrence parser, which would refuse // all of it and leave the task not repeating at all. +// +// Mellemleddet må være et ord og ikke kun et tal. "hver anden tirsdag" er den måde, +// folk siger det på — recurrence-pakken har oversat "hver anden" til "hver 2." +// siden den blev skrevet — men her stoppede mønsteret efter "anden" og gav den +// sætning videre. Den er ikke en regel, så "hver anden" blev stående i titlen og +// "tirsdag" blev en forfaldsdato. Sløjfen nedenfor kan kun *fjerne* ord fra +// enden; den kan ikke hente et, mønsteret aldrig tog med. +// +// Fundet af en prøve, der brugte vendingen som selvfølgelig og opdagede, at den +// ikke var det. var reRepeat = regexp.MustCompile( - `(?i)(?:^|\s)((?:hver|hvert|every|each)\s+(?:\d+\.?\s+)?[\p{L}]+(?:\s*(?:,|\bog\b|\band\b)\s*[\p{L}]+)*` + + `(?i)(?:^|\s)((?:hver|hvert|every|each)\s+(?:\d+\.?\s+|(?:anden|andet|tredje|fjerde|femte|sjette|other)\s+)?[\p{L}]+(?:\s*(?:,|\bog\b|\band\b)\s*[\p{L}]+)*` + `|hverdage|ugedage|weekdays?|dagligt|daily|ugentligt|weekly|månedligt|maanedligt|monthly|årligt|aarligt|yearly|annually` + `|den\s+\d{1,2}\.?\s+i\s+måneden|den\s+\d{1,2}\.?\s+i\s+maaneden)(?:\s|$)`) diff --git a/internal/quickadd/quickadd_test.go b/internal/quickadd/quickadd_test.go index c6dedde..aacc761 100644 --- a/internal/quickadd/quickadd_test.go +++ b/internal/quickadd/quickadd_test.go @@ -603,3 +603,36 @@ func TestASectionIsWrittenWithASlash(t *testing.T) { } } } + +// "hver anden tirsdag" er den måde, folk siger det på. +// +// recurrence-pakken har oversat "hver anden" til "hver 2." siden den blev skrevet, +// men sætningen nåede aldrig frem til den: mønsteret her tog kun ét ord efter +// "hver", så det, der blev givet videre, var "hver anden" — ikke en regel. Så blev +// de to ord stående i titlen, og "tirsdag" blev til en forfaldsdato. Opgaven +// gentog sig ikke, og der stod ikke noget om det. +// +// Fundet af en prøve, der brugte vendingen som selvfølgelig og opdagede, at den +// ikke var det. +func TestEveryOtherWeekdayIsARepetition(t *testing.T) { + for _, tc := range []struct { + text string + rule string + left string + }{ + {"vande planterne hver anden tirsdag", "FREQ=WEEKLY;BYDAY=TU;INTERVAL=2", "vande planterne"}, + {"vande planterne hver 2. tirsdag", "FREQ=WEEKLY;BYDAY=TU;INTERVAL=2", "vande planterne"}, + {"water the plants every other tuesday", "FREQ=WEEKLY;BYDAY=TU;INTERVAL=2", "water the plants"}, + {"gå tur hver tredje søndag", "FREQ=WEEKLY;BYDAY=SU;INTERVAL=3", "gå tur"}, + // Den, der virkede i forvejen, skal blive ved med at gøre det. + {"tømme opvasker hver mandag", "FREQ=WEEKLY;BYDAY=MO", "tømme opvasker"}, + } { + got := Parse(tc.text, time.Date(2026, 8, 20, 9, 0, 0, 0, time.UTC), "da") + if got.Recurrence != tc.rule { + t.Errorf("%q gav reglen %q, want %q", tc.text, got.Recurrence, tc.rule) + } + if got.Content != tc.left { + t.Errorf("%q efterlod titlen %q, want %q", tc.text, got.Content, tc.left) + } + } +}