From c7764ca3a0c56e4712f1c12eb8f2013a8570c5c7 Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Thu, 10 Mar 2016 09:22:09 -0500 Subject: [PATCH] [1.8.x] Fixed #26324 -- Fixed DurationField with fractional seconds on SQLite. Backport of 4f0cd0fd162122da96978b357ac9fc9534529410 from master --- django/db/models/fields/__init__.py | 3 ++- docs/releases/1.8.12.txt | 3 +++ tests/model_fields/test_durationfield.py | 6 ++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index e0534b823b..8bba4cb321 100644 --- a/django/db/models/fields/__init__.py +++ b/django/db/models/fields/__init__.py @@ -1680,7 +1680,8 @@ class DurationField(Field): return value if value is None: return None - return value.total_seconds() * 1000000 + # Discard any fractional microseconds due to floating point arithmetic. + return int(round(value.total_seconds() * 1000000)) def get_db_converters(self, connection): converters = [] diff --git a/docs/releases/1.8.12.txt b/docs/releases/1.8.12.txt index 26735b8278..0052a90b0d 100644 --- a/docs/releases/1.8.12.txt +++ b/docs/releases/1.8.12.txt @@ -12,3 +12,6 @@ Bugfixes * Made ``MultiPartParser`` ignore filenames that normalize to an empty string to fix crash in ``MemoryFileUploadHandler`` on specially crafted user input (:ticket:`26325`). + +* Fixed data loss on SQLite where ``DurationField`` values with fractional + seconds could be saved as ``None`` (:ticket:`26324`). diff --git a/tests/model_fields/test_durationfield.py b/tests/model_fields/test_durationfield.py index fece35d57b..16a84a3e2b 100644 --- a/tests/model_fields/test_durationfield.py +++ b/tests/model_fields/test_durationfield.py @@ -22,6 +22,12 @@ class TestSaveLoad(TestCase): loaded = NullDurationModel.objects.get() self.assertEqual(loaded.field, None) + def test_fractional_seconds(self): + value = datetime.timedelta(seconds=2.05) + d = DurationModel.objects.create(field=value) + d.refresh_from_db() + self.assertEqual(d.field, value) + class TestQuerying(TestCase):