From 735681d294db31faca594a4d8d41c320c458f467 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Sat, 28 Jun 2025 21:39:14 -0700 Subject: [PATCH] Fix: correct api created coercion with timezone (#10287) --- src/documents/serialisers.py | 14 +++++++++----- src/documents/tests/test_api_documents.py | 21 +++++++++++++++++++++ 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/documents/serialisers.py b/src/documents/serialisers.py index 0abc96731..48497ce19 100644 --- a/src/documents/serialisers.py +++ b/src/documents/serialisers.py @@ -18,7 +18,11 @@ from django.core.validators import MaxLengthValidator from django.core.validators import RegexValidator from django.core.validators import integer_validator from django.utils.crypto import get_random_string +from django.utils.dateparse import parse_datetime from django.utils.text import slugify +from django.utils.timezone import get_current_timezone +from django.utils.timezone import is_naive +from django.utils.timezone import make_aware from django.utils.translation import gettext as _ from drf_spectacular.utils import extend_schema_field from drf_spectacular.utils import extend_schema_serializer @@ -972,11 +976,11 @@ class DocumentSerializer( and ":" in data["created"] ): # Handle old format of isoformat datetime string - try: - data["created"] = datetime.fromisoformat(data["created"]).date() - except ValueError: # pragma: no cover - # Just pass, validation will catch it - pass + parsed = parse_datetime(data["created"]) + if parsed: + if is_naive(parsed): + parsed = make_aware(parsed, get_current_timezone()) + data["created"] = parsed.astimezone().date() return super().to_internal_value(data) def validate(self, attrs): diff --git a/src/documents/tests/test_api_documents.py b/src/documents/tests/test_api_documents.py index dd4236718..77d099b85 100644 --- a/src/documents/tests/test_api_documents.py +++ b/src/documents/tests/test_api_documents.py @@ -203,6 +203,27 @@ class TestDocumentApi(DirectoriesMixin, DocumentConsumeDelayMixin, APITestCase): self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data["created"], "2023-01-01") + # legacy datetime format + response = self.client.patch( + f"/api/documents/{doc.pk}/", + {"created": "2023-02-01T23:00:00Z"}, + format="json", + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + doc.refresh_from_db() + self.assertEqual(doc.created, date(2023, 2, 1)) + + # naive datetime + response = self.client.patch( + f"/api/documents/{doc.pk}/", + {"created": "2023-06-28T23:00:00"}, + format="json", + ) + + self.assertEqual(response.status_code, status.HTTP_200_OK) + doc.refresh_from_db() + self.assertEqual(doc.created, date(2023, 6, 28)) + def test_document_update_legacy_created_format(self): """ GIVEN: