aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrock Mendel <jbrockmendel@gmail.com>2018-04-20 20:25:29 -0700
committerPaul Ganssle <paul@ganssle.io>2018-05-07 12:44:27 -0400
commit3364cdb0abcf6be4ce15ef3b2db68b35711229f5 (patch)
treee3dff5dff645f8d4f3077b9adccc5829cafe37e0
parenteaa174d4cd7d7a58ae94b0a53f969539c687f916 (diff)
downloaddateutil-3364cdb0abcf6be4ce15ef3b2db68b35711229f5.tar.gz
Fix for B.Y.d format corner case #687
Add changelog file
-rw-r--r--changelog.d/687.bugfix.rst1
-rw-r--r--dateutil/parser/_parser.py40
-rw-r--r--dateutil/test/test_parser.py6
3 files changed, 43 insertions, 4 deletions
diff --git a/changelog.d/687.bugfix.rst b/changelog.d/687.bugfix.rst
new file mode 100644
index 0000000..7f83add
--- /dev/null
+++ b/changelog.d/687.bugfix.rst
@@ -0,0 +1 @@
+Fixed incorrect parsing of certain dates earlier than 100 AD when repesented in the form "%B.%Y.%d", e.g. "December.0031.30". (gh issue #687, pr #700)
diff --git a/dateutil/parser/_parser.py b/dateutil/parser/_parser.py
index f749bdf..04bc539 100644
--- a/dateutil/parser/_parser.py
+++ b/dateutil/parser/_parser.py
@@ -458,10 +458,38 @@ class _ymd(list):
raise ValueError('Year is already set')
self.ystridx = len(self) - 1
+ def _resolve_from_stridxs(self):
+ """
+ Try to resolve the identities of year/month/day elements using
+ ystridx, mstridx, and dstridx, if enough of these are specified.
+ """
+ strids = {'y': self.ystridx, 'm': self.mstridx, 'd': self.dstridx}
+ strids = {key: strids[key] for key in strids if strids[key] is not None}
+
+ if len(self) == 3 and len(strids) == 2:
+ # we can back out the remaining stridx value
+ missing = [x for x in range(3) if x not in strids.values()]
+ key = [x for x in ['y', 'm', 'd'] if x not in strids]
+ assert len(missing) == len(key) == 1
+ key = key[0]
+ val = missing[0]
+ strids[key] = val
+
+ assert len(self) == len(strids) # otherwise this should not be called
+ out = {'y': None, 'm': None, 'd': None}
+ out.update({key: self[strids[key]] for key in strids})
+ return (out['y'], out['m'], out['d'])
+
def resolve_ymd(self, yearfirst, dayfirst):
len_ymd = len(self)
year, month, day = (None, None, None)
+ strids = {'y': self.ystridx, 'm': self.mstridx, 'd': self.dstridx}
+ strids = {key: strids[key] for key in strids if strids[key] is not None}
+ if (len(self) == len(strids) > 0 or
+ (len(self) == 3 and len(strids) == 2)):
+ return self._resolve_from_stridxs()
+
mstridx = self.mstridx
if len_ymd > 3:
@@ -470,13 +498,17 @@ class _ymd(list):
# One member, or two members with a month string
if mstridx is not None:
month = self[mstridx]
- del self[mstridx]
+ # since mstridx is 0 or 1, self[mstridx-1] always
+ # looks up the other element
+ other = self[mstridx - 1]
+ else:
+ other = self[0]
if len_ymd > 1 or mstridx is None:
- if self[0] > 31:
- year = self[0]
+ if other > 31:
+ year = other
else:
- day = self[0]
+ day = other
elif len_ymd == 2:
# Two members with numbers
diff --git a/dateutil/test/test_parser.py b/dateutil/test/test_parser.py
index 029f672..f8c2072 100644
--- a/dateutil/test/test_parser.py
+++ b/dateutil/test/test_parser.py
@@ -1106,3 +1106,9 @@ def test_decimal_error(value):
# constructed with an invalid value
with pytest.raises(ValueError):
parse(value)
+
+
+def test_BYd_corner_case():
+ # GH#687
+ res = parse('December.0031.30')
+ assert res == datetime(31, 12, 30)