diff options
-rw-r--r-- | AUTHORS.md | 1 | ||||
-rw-r--r-- | dateutil/parser/_parser.py | 10 | ||||
-rw-r--r-- | dateutil/test/test_parser.py | 10 |
3 files changed, 18 insertions, 3 deletions
@@ -41,6 +41,7 @@ Apache 2.0 and BSD 3-clause. In the list below, anyone whose name is marked with - Kubilay Kocak <koobs@MASKED> - Laszlo Kiss Kollar <kiss.kollar.laszlo@MASKED> (gh: @lkollar) - Mario Corchero <mcorcherojim@MASKED> (gh: @mariocj89) **R** +- Mateusz Dziedzic (gh: @m-dz) - Matthew Schinckel <matt@MASKED> - Max Shenfield <shenfieldmax@MASKED> - Maxime Lorant <maxime.lorant@MASKED> diff --git a/dateutil/parser/_parser.py b/dateutil/parser/_parser.py index 2291f39..82be944 100644 --- a/dateutil/parser/_parser.py +++ b/dateutil/parser/_parser.py @@ -42,6 +42,8 @@ from io import StringIO import six from six import binary_type, integer_types, text_type +from decimal import Decimal + from .. import relativedelta from .. import tz @@ -873,7 +875,7 @@ class parser(object): def _parse_numeric_token(self, tokens, idx, info, ymd, res, fuzzy): # Token is a number value_repr = tokens[idx] - value = float(value_repr) + value = Decimal(value_repr) len_li = len(value_repr) len_l = len(tokens) @@ -932,7 +934,7 @@ class parser(object): elif idx + 2 < len_l and tokens[idx + 1] == ':': # HH:MM[:SS[.ss]] res.hour = int(value) - value = float(tokens[idx + 2]) # TODO: try/except for this? + value = Decimal(tokens[idx + 2]) # TODO: try/except for this? (res.minute, res.second) = self._parse_min_sec(value) if idx + 4 < len_l and tokens[idx + 3] == ':': @@ -1032,7 +1034,9 @@ class parser(object): return hms_idx def _assign_hms(self, res, value_repr, hms): - value = float(value_repr) + # See GH issue #427, fixing float rounding + value = Decimal(value_repr) + if hms == 0: # Hour res.hour = int(value) diff --git a/dateutil/test/test_parser.py b/dateutil/test/test_parser.py index c658c01..ce27e82 100644 --- a/dateutil/test/test_parser.py +++ b/dateutil/test/test_parser.py @@ -1077,3 +1077,13 @@ def test_parse_tzinfos_fold(): assert dt.tzinfo is dt_exp.tzinfo assert getattr(dt, 'fold') == getattr(dt_exp, 'fold') assert dt.astimezone(tz.tzutc()) == dt_exp.astimezone(tz.tzutc()) + + +@pytest.mark.parametrize('dtstr,dt', [ + ('5.6h', datetime(2003, 9, 25, 5, 36)), + ('5.6m', datetime(2003, 9, 25, 0, 5, 36)), + # '5.6s' never had a rounding problem, test added for completeness + ('5.6s', datetime(2003, 9, 25, 0, 0, 5, 600000)) +]) +def test_rounding_floatlike_strings(dtstr, dt): + assert parse(dtstr, default=datetime(2003, 9, 25)) == dt |