Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
10 changes: 7 additions & 3 deletions dateutil/parser/_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
import six
from six import binary_type, integer_types, text_type

from decimal import Decimal

from .. import relativedelta
from .. import tz

Expand Down Expand Up @@ -873,7 +875,7 @@ def _parse(self, timestr, dayfirst=None, yearfirst=None, fuzzy=False,
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)
Expand Down Expand Up @@ -932,7 +934,7 @@ def _parse_numeric_token(self, tokens, idx, info, ymd, res, fuzzy):
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] == ':':
Expand Down Expand Up @@ -1032,7 +1034,9 @@ def _find_hms_idx(self, idx, tokens, info, allow_jump):
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)
Expand Down
10 changes: 10 additions & 0 deletions dateutil/test/test_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -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