Merge the bare-hour fix (#193)
V-551. "завтра в семь" booked the reminder for the current clock. dateparser needs the colon, so the script gives it one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SoL7EBdYC5Mhz3DJd49GJy
This commit is contained in:
@@ -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'(?<![\w:])(в|во|at)\s+([01]?\d|2[0-3])(?:\s+час(?:а|ов)?)?(?![\d:.\w])',
|
||||
lambda m: '%s %02d:00' % (m.group(1), int(m.group(2))), text, flags=re.IGNORECASE)
|
||||
settings = {'PREFER_DATES_FROM': 'future', 'RELATIVE_BASE': now}
|
||||
# Two-step: search_dates finds the date substring in text,
|
||||
# parse() gets the time right (search_dates mishandles AM/PM).
|
||||
|
||||
@@ -103,6 +103,53 @@ func TestPythonDateParser(t *testing.T) {
|
||||
}
|
||||
},
|
||||
},
|
||||
// A bare hour after a day word used to be dropped, and the current
|
||||
// clock carried onto that day: at 21:12 "завтра в семь" confirmed a
|
||||
// reminder for 21:12 tomorrow (Vikunja #551). She invented a time
|
||||
// instead of asking, on a path that then fires.
|
||||
{
|
||||
name: "ru bare hour — завтра в семь",
|
||||
text: "напомни мне завтра в семь позвонить маме",
|
||||
wantOK: true,
|
||||
checkT: func(t *testing.T, got, now time.Time) {
|
||||
if got.Hour() != 7 || got.Minute() != 0 {
|
||||
t.Errorf("завтра в семь: %02d:%02d, want 07:00", got.Hour(), got.Minute())
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
// "7 часов" was read as seven hours from now, which also moved the day.
|
||||
name: "ru bare hour — завтра в 7 часов",
|
||||
text: "напомни завтра в 7 часов позвонить",
|
||||
wantOK: true,
|
||||
checkT: func(t *testing.T, got, now time.Time) {
|
||||
if got.Hour() != 7 || got.Minute() != 0 {
|
||||
t.Errorf("завтра в 7 часов: %02d:%02d, want 07:00", got.Hour(), got.Minute())
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "en bare hour — tomorrow at 7",
|
||||
text: "remind me tomorrow at 7 to call mum",
|
||||
wantOK: true,
|
||||
checkT: func(t *testing.T, got, now time.Time) {
|
||||
if got.Hour() != 7 || got.Minute() != 0 {
|
||||
t.Errorf("tomorrow at 7: %02d:%02d, want 07:00", got.Hour(), got.Minute())
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
// The rewrite must not touch a duration: "через 2 часа" is not "в 2".
|
||||
name: "ru duration is untouched — через 2 часа",
|
||||
text: "напомни через 2 часа выпить воды",
|
||||
wantOK: true,
|
||||
checkT: func(t *testing.T, got, now time.Time) {
|
||||
d := got.Sub(now)
|
||||
if d < 110*time.Minute || d > 130*time.Minute {
|
||||
t.Errorf("через 2 часа: got %v from now, want ~2h", d)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no date — напомни мне",
|
||||
text: "напомни мне",
|
||||
|
||||
Reference in New Issue
Block a user