From 44320ee496f4023f57dab4682b647dff0e9019e4 Mon Sep 17 00:00:00 2001 From: claude Date: Wed, 5 Aug 2026 21:17:21 +0400 Subject: [PATCH] dates: a bare hour after a day word is an hour, not the current clock (V-551) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At 21:12 "напомни мне завтра в семь позвонить маме" confirmed a reminder for 21:12 tomorrow. The hour was dropped and the wall clock carried onto the named day. She did not ask; she named a time nobody gave her, on a path that fires. A bare "напомни в семь" declines correctly, so adding "завтра" turned a decline into an invented answer. dateparser only reads a bare hour when it carries a qualifier or a colon. "завтра в 7" keeps the current clock and "завтра в 7 часов" is read as seven hours from now, which moves the day as well. English "at 7" fails identically, so this is not a Russian defect and both prepositions are rewritten. The script now gives it the colon: "в 7", "в 7 часов" and "at 7" become "в 07:00" beside the existing утра/вечера rewrites. A duration is untouched, because "через 2 часа" has no preposition to match, and so are "в 7:30", "в 30 минут" and "в 2026 году". The stub parser has always read the token after the day word, so the floor was right and the production parser was not. No test on the stub could have caught this. The four new cases are in TestPythonDateParser, which runs where dateparser is installed. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01SoL7EBdYC5Mhz3DJd49GJy --- internal/router/dateparser.go | 7 +++++ internal/router/dateparser_test.go | 47 ++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/internal/router/dateparser.go b/internal/router/dateparser.go index 908dfee..fe13e1b 100644 --- a/internal/router/dateparser.go +++ b/internal/router/dateparser.go @@ -49,6 +49,13 @@ try: text = re.sub(r'(\d+)\s+(?:час(?:а|ов)?\s+)?вечера\b', r'\1 pm', text, flags=re.IGNORECASE) text = re.sub(r'(\d+)\s+(?:час(?:а|ов)?\s+)?дня\b', r'\1 pm', text, flags=re.IGNORECASE) text = re.sub(r'(\d+)\s+(?:час(?:а|ов)?\s+)?ночи\b', r'\1 am', text, flags=re.IGNORECASE) + # A bare hour after a preposition is dropped on the floor by dateparser: + # "завтра в 7" resolves to tomorrow at the CURRENT clock, and "завтра в 7 + # часов" is read as seven hours from now. Only a qualifier (already an + # am/pm above) or a colon makes it read the hour, so give it the colon. + # English "at 7" fails identically, so both prepositions are rewritten. + text = re.sub(r'(? 130*time.Minute { + t.Errorf("через 2 часа: got %v from now, want ~2h", d) + } + }, + }, { name: "no date — напомни мне", text: "напомни мне",