Fix NL parser: fuzzy tomorrow matching + relative date offsets
Handles tommorow/tomorow/tomarrow misspellings. Adds "in N days", "in N weeks", and "next week" recognition with numeric and word forms.
This commit is contained in:
@@ -764,7 +764,7 @@ struct NLTaskParser {
|
||||
// ── Day keywords ───────────────────────────────────────────────────
|
||||
let dayTable: [(String, Int)] = [
|
||||
("\\btoday\\b", 0),
|
||||
("\\btomorrow\\b", 1),
|
||||
("\\btom+[ao]r+ow\\b", 1),
|
||||
("\\bmon(day)?\\b", daysUntil(2)),
|
||||
("\\btue(sday)?\\b", daysUntil(3)),
|
||||
("\\bwed(nesday)?\\b", daysUntil(4)),
|
||||
@@ -773,11 +773,20 @@ struct NLTaskParser {
|
||||
("\\bsat(urday)?\\b", daysUntil(7)),
|
||||
("\\bsun(day)?\\b", daysUntil(1)),
|
||||
]
|
||||
for (pat, offset) in dayTable {
|
||||
if let r = match(pat, in: lower) {
|
||||
let d = cal.date(byAdding: .day, value: offset, to: Date()) ?? Date()
|
||||
comps = cal.dateComponents([.year, .month, .day], from: d)
|
||||
rawRanges.append(r); foundDay = true; break
|
||||
// ── Relative offsets ("in N days", "next week") ───────────────────
|
||||
if let (r, offset) = parseRelativeOffset(in: lower) {
|
||||
let d = cal.date(byAdding: .day, value: offset, to: Date()) ?? Date()
|
||||
comps = cal.dateComponents([.year, .month, .day], from: d)
|
||||
rawRanges.append(r); foundDay = true
|
||||
}
|
||||
|
||||
if !foundDay {
|
||||
for (pat, offset) in dayTable {
|
||||
if let r = match(pat, in: lower) {
|
||||
let d = cal.date(byAdding: .day, value: offset, to: Date()) ?? Date()
|
||||
comps = cal.dateComponents([.year, .month, .day], from: d)
|
||||
rawRanges.append(r); foundDay = true; break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -814,6 +823,22 @@ struct NLTaskParser {
|
||||
.replacingOccurrences(of: " ", with: " ")
|
||||
}
|
||||
|
||||
private static func parseRelativeOffset(in text: String) -> (NSRange, Int)? {
|
||||
let wordNums = ["a": 1, "an": 1, "one": 1, "two": 2, "three": 3, "four": 4,
|
||||
"five": 5, "six": 6, "seven": 7, "eight": 8, "nine": 9, "ten": 10]
|
||||
if let r = match("\\bnext\\s+week\\b", in: text) { return (r, 7) }
|
||||
for (unit, mult) in [("days?", 1), ("weeks?", 7)] {
|
||||
let pat = "\\bin\\s+(\\d+|a|an|one|two|three|four|five|six|seven|eight|nine|ten)\\s+\(unit)\\b"
|
||||
guard let rx = try? NSRegularExpression(pattern: pat),
|
||||
let m = rx.firstMatch(in: text, range: NSRange(text.startIndex..., in: text)),
|
||||
m.numberOfRanges >= 2,
|
||||
let nr = Range(m.range(at: 1), in: text) else { continue }
|
||||
let ns = String(text[nr])
|
||||
return (m.range, (Int(ns) ?? wordNums[ns] ?? 1) * mult)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
private static func daysUntil(_ target: Int) -> Int {
|
||||
let today = Calendar.current.component(.weekday, from: Date())
|
||||
let d = target - today
|
||||
|
||||
Reference in New Issue
Block a user