Skip to content

Commit

Permalink
Use decimal rounding to fix high precision timedelta errors
Browse files Browse the repository at this point in the history
  • Loading branch information
deckar01 committed Aug 20, 2021
1 parent e17b7d5 commit df99e19
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 1 deletion.
4 changes: 3 additions & 1 deletion src/marshmallow/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -1471,7 +1471,9 @@ def _serialize(self, value, attr, obj, **kwargs):
if value is None:
return None
base_unit = dt.timedelta(**{self.precision: 1})
return int(value.total_seconds() / base_unit.total_seconds())
delta = round(decimal.Decimal(value.total_seconds()), 9)
unit = round(decimal.Decimal(base_unit.total_seconds()), 9)
return int(delta / unit)

def _deserialize(self, value, attr, data, **kwargs):
try:
Expand Down
9 changes: 9 additions & 0 deletions tests/test_serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,15 @@ def test_timedelta_field(self, user):
user.d7 = None
assert field.serialize("d7", user) is None

# https://github.com/marshmallow-code/marshmallow/issues/1856
user.d8 = dt.timedelta(milliseconds=345)
field = fields.TimeDelta(fields.TimeDelta.MILLISECONDS)
assert field.serialize("d8", user) == 345

user.d9 = dt.timedelta(milliseconds=1999)
field = fields.TimeDelta(fields.TimeDelta.SECONDS)
assert field.serialize("d9", user) == 1

def test_datetime_list_field(self):
obj = DateTimeList([dt.datetime.utcnow(), dt.datetime.now()])
field = fields.List(fields.DateTime)
Expand Down

0 comments on commit df99e19

Please sign in to comment.