Repository: MycroftAI/lingua-franca

Issue:
"In 2007" should be parsed as year
**Describe the bug**
I know for Mycroft it reasonable to parse 2007 as 20:07. But this is a separate library, and for 2007 should be a year.

**To Reproduce**
```python
from lingua_franca.parse import *
lingua_franca.load_language('en')
print(lingua_franca.parse.extract_datetime('in 2007'))
[datetime.datetime(2022, 2, 21, 20, 7), '']
```


**Expected behavior**
[datetime.datetime(2007, 0, 0, 0, 0), '']

**env**
lingua_franca-0.4.2-py3-none-any.whl
python3.9

Discussion:

Patch:
diff --git a/lingua_franca/lang/parse_en.py b/lingua_franca/lang/parse_en.py
index 0a8b8e1..3075715 100644
--- a/lingua_franca/lang/parse_en.py
+++ b/lingua_franca/lang/parse_en.py
@@ -694,7 +694,8 @@ def extract_datetime_en(text, anchorDate=None, default_time=None):
     timeQualifiersAM = ['morning']
     timeQualifiersPM = ['afternoon', 'evening', 'night', 'tonight']
     timeQualifiersList = set(timeQualifiersAM + timeQualifiersPM)
-    markers = ['at', 'in', 'on', 'by', 'this', 'around', 'for', 'of', "within"]
+    year_markers = ['in', 'on', 'of']
+    markers = year_markers + ['at', 'by', 'this', 'around', 'for', "within"]
     days = ['monday', 'tuesday', 'wednesday',
             'thursday', 'friday', 'saturday', 'sunday']
     months = ['january', 'february', 'march', 'april', 'may', 'june',
@@ -743,6 +744,10 @@ def extract_datetime_en(text, anchorDate=None, default_time=None):
                 yearOffset = multiplier * 100
             elif wordNext == "millennium":
                 yearOffset = multiplier * 1000
+        elif word in year_markers and is_numeric(wordNext) and len(wordNext) == 4:
+            yearOffset = int(wordNext) - int(currentYear)
+            used += 2
+            hasYear = True
         # couple of
         elif word == "2" and wordNext == "of" and \
                 wordNextNext in year_multiples:
@@ -792,7 +797,7 @@ def extract_datetime_en(text, anchorDate=None, default_time=None):
             if wordPrev == "the":
                 start -= 1
                 used += 1
-                # parse 5 days, 10 weeks, last week, next week
+        # parse 5 days, 10 weeks, last week, next week
         elif word == "day":
             if wordPrev and wordPrev[0].isdigit():
                 dayOffset += int(wordPrev)
@@ -811,7 +816,7 @@ def extract_datetime_en(text, anchorDate=None, default_time=None):
                 dayOffset = -7
                 start -= 1
                 used = 2
-                # parse 10 months, next month, last month
+        # parse 10 months, next month, last month
         elif word == "month" and not fromFlag and wordPrev:
             if wordPrev[0].isdigit():
                 monthOffset = int(wordPrev)
@@ -856,7 +861,7 @@ def extract_datetime_en(text, anchorDate=None, default_time=None):
                 dayOffset -= 7
                 used += 1
                 start -= 1
-                # parse 15 of July, June 20th, Feb 18, 19 of February
+        # parse 15 of July, June 20th, Feb 18, 19 of February
         elif word in months or word in monthsShort and not fromFlag:
             try:
                 m = months.index(word)
diff --git a/requirements.txt b/requirements.txt
index d431540..be56c7a 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,1 +1,1 @@
-python-dateutil==2.6.0
\ No newline at end of file
+python-dateutil~=2.6.0
\ No newline at end of file


Test patch:
diff --git a/test/test_parse.py b/test/test_parse.py
index a494cc2..7ee6b78 100644
--- a/test/test_parse.py
+++ b/test/test_parse.py
@@ -710,6 +710,11 @@ class TestNormalize(unittest.TestCase):
         testExtract("what's the weather like next tuesday night",
                     "2017-07-04 22:00:00", "what is weather like night")
 
+    def test_extract_date_years(self):
+        date = datetime(2017, 6, 27, tzinfo=default_timezone())  # Tue June 27, 2017
+        self.assertEqual(extract_datetime('in 2007', date)[0],
+            datetime(2007, 6, 27, tzinfo=date.tzinfo))
+
     def test_extract_ambiguous_time_en(self):
         morning = datetime(2017, 6, 27, 8, 1, 2, tzinfo=default_timezone())
         evening = datetime(2017, 6, 27, 20, 1, 2, tzinfo=default_timezone())