From 72c1ed366dcdbf1f5f86b2ebf93f9f128254575e Mon Sep 17 00:00:00 2001 From: JarbasAI <33701864+JarbasAl@users.noreply.github.com> Date: Sat, 11 Jan 2020 15:40:08 +0000 Subject: [PATCH] bugfix/ handle "yesterday"/ "X days ago" (#38) partially solves https://github.com/MycroftAI/mycroft-core/issues/2369 fixes extraction of "yesterday", "X days from yesterday", "before yesterday", "X days ago" Authored-by: @JarbasAl --- lingua_franca/lang/parse_en.py | 19 +++++++++++++-- test/test_parse.py | 43 +++++++++++++++++++++++++++++++--- 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/lingua_franca/lang/parse_en.py b/lingua_franca/lang/parse_en.py index 5a90f18e..58207de2 100644 --- a/lingua_franca/lang/parse_en.py +++ b/lingua_franca/lang/parse_en.py @@ -677,7 +677,9 @@ def date_found(): start = idx used = 0 # save timequalifier for later - + if word == "ago" and dayOffset: + dayOffset = - dayOffset + used += 1 if word == "now" and not datestr: resultStr = " ".join(words[idx + 1:]) resultStr = ' '.join(resultStr.split()) @@ -726,6 +728,15 @@ def date_found(): elif word == "tomorrow" and not fromFlag: dayOffset = 1 used += 1 + elif word == "day" and wordNext == "before" and wordNextNext == "yesterday" and not fromFlag: + dayOffset = -2 + used += 3 + elif word == "before" and wordNext == "yesterday" and not fromFlag: + dayOffset = -2 + used += 2 + elif word == "yesterday" and not fromFlag: + dayOffset = -1 + used += 1 elif (word == "day" and wordNext == "after" and wordNextNext == "tomorrow" and @@ -846,6 +857,7 @@ def date_found(): validFollowups = days + months + monthsShort validFollowups.append("today") validFollowups.append("tomorrow") + validFollowups.append("yesterday") validFollowups.append("next") validFollowups.append("last") validFollowups.append("now") @@ -855,6 +867,8 @@ def date_found(): fromFlag = True if wordNext == "tomorrow": dayOffset += 1 + elif wordNext == "yesterday": + dayOffset -= 1 elif wordNext in days: d = days.index(wordNext) tmpOffset = (d + 1) - int(today) @@ -1230,7 +1244,8 @@ def date_found(): remainder not in ['am', 'pm', 'hours', 'minutes', "second", "seconds", "hour", "minute"] and - ((not daySpecified) or dayOffset < 1)): + ((not daySpecified) or 0 <= dayOffset < 1)): + # ambiguous time, detect whether they mean this evening or # the next morning based on whether it has already passed if dateNow.hour < HH or (dateNow.hour == HH and diff --git a/test/test_parse.py b/test/test_parse.py index 5a249a81..01aec528 100644 --- a/test/test_parse.py +++ b/test/test_parse.py @@ -175,12 +175,12 @@ def test_extract_duration_en(self): self.assertEqual(extract_duration("7.5 seconds"), (timedelta(seconds=7.5), "")) self.assertEqual(extract_duration("eight and a half days thirty" - " nine seconds"), + " nine seconds"), (timedelta(days=8.5, seconds=39), "")) self.assertEqual(extract_duration("Set a timer for 30 minutes"), (timedelta(minutes=30), "set a timer for")) self.assertEqual(extract_duration("Four and a half minutes until" - " sunset"), + " sunset"), (timedelta(minutes=4.5), "until sunset")) self.assertEqual(extract_duration("Nineteen minutes past the hour"), (timedelta(minutes=19), "past the hour")) @@ -188,7 +188,7 @@ def test_extract_duration_en(self): " hundred ninety seven days, and" " three hundred 91.6 seconds"), (timedelta(weeks=3, days=497, seconds=391.6), - "wake me up in , , and")) + "wake me up in , , and")) self.assertEqual(extract_duration("The movie is one hour, fifty seven" " and a half minutes long"), (timedelta(hours=1, minutes=57.5), @@ -485,6 +485,18 @@ def testExtract(text, expected_date, expected_leftover): "2017-07-01 10:00:00", "remind me to call mom") testExtract("remind me to call mom at 10am next saturday", "2017-07-01 10:00:00", "remind me to call mom") + # test yesterday + testExtract("what day was yesterday", + "2017-06-26 00:00:00", "what day was") + testExtract("what day was the day before yesterday", + "2017-06-25 00:00:00", "what day was") + testExtract("i had dinner yesterday at 6", + "2017-06-26 06:00:00", "i had dinner") + testExtract("i had dinner yesterday at 6 am", + "2017-06-26 06:00:00", "i had dinner") + testExtract("i had dinner yesterday at 6 pm", + "2017-06-26 18:00:00", "i had dinner") + # Below two tests, ensure that time is picked # even if no am/pm is specified # in case of weekdays/tonight @@ -507,6 +519,31 @@ def testExtract(text, expected_date, expected_leftover): testExtract("set alarm at 7:30 on weekdays", "2017-06-27 19:30:00", "set alarm on weekdays") + # "# days " + testExtract("my birthday is 2 days from today", + "2017-06-29 00:00:00", "my birthday is") + testExtract("my birthday is 2 days after today", + "2017-06-29 00:00:00", "my birthday is") + testExtract("my birthday is 2 days from tomorrow", + "2017-06-30 00:00:00", "my birthday is") + testExtract("my birthday is 2 days after tomorrow", + "2017-06-30 00:00:00", "my birthday is") + testExtract("remind me to call mom at 10am 2 days after next saturday", + "2017-07-10 10:00:00", "remind me to call mom") + testExtract("my birthday is 2 days from yesterday", + "2017-06-28 00:00:00", "my birthday is") + testExtract("my birthday is 2 days after yesterday", + "2017-06-28 00:00:00", "my birthday is") + + # "# days ago>" + testExtract("my birthday was 1 day ago", + "2017-06-26 00:00:00", "my birthday was") + testExtract("my birthday was 2 days ago", + "2017-06-25 00:00:00", "my birthday was") + testExtract("my birthday was 3 days ago", + "2017-06-24 00:00:00", "my birthday was") + testExtract("my birthday was 4 days ago", + "2017-06-23 00:00:00", "my birthday was") # TODO this test is imperfect due to "tonight" in the reminder, but let is pass since the date is correct testExtract("lets meet tonight", "2017-06-27 22:00:00", "lets meet tonight")