From c483de1b7fab190fc0660cc0fa1c74dc63bc5bef Mon Sep 17 00:00:00 2001 From: Sanjay Santhanam <51058514+Sanjays2402@users.noreply.github.com> Date: Thu, 6 Aug 2026 02:17:40 -0700 Subject: [PATCH] fix: skip truncate_datetime for date and timedelta objects DeepDiff(..., truncate_datetime=...) raised TypeError for datetime.date values ('replace() got an unexpected keyword argument microsecond') and AttributeError for datetime.timedelta values, because datetime_normalize applied the truncation unconditionally to every value routed through it. date has no time components to truncate and timedelta has no replace(), so the truncation is now applied only to datetime and time objects. Truncation of datetime/time values is unchanged. Fixes #564 --- deepdiff/helper.py | 2 +- tests/test_diff_datetime.py | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/deepdiff/helper.py b/deepdiff/helper.py index 3fc61183..45379caa 100644 --- a/deepdiff/helper.py +++ b/deepdiff/helper.py @@ -690,7 +690,7 @@ def datetime_normalize( datetime.timezone, "BaseTzInfo" ] = datetime.timezone.utc, ) -> Any: - if truncate_datetime: + if truncate_datetime and isinstance(obj, (datetime.datetime, datetime.time)): if truncate_datetime == 'second': obj = obj.replace(microsecond=0) elif truncate_datetime == 'minute': diff --git a/tests/test_diff_datetime.py b/tests/test_diff_datetime.py index c3905291..1b48642a 100644 --- a/tests/test_diff_datetime.py +++ b/tests/test_diff_datetime.py @@ -1,5 +1,5 @@ import pytz -from datetime import date, datetime, time, timezone +from datetime import date, datetime, time, timedelta, timezone from deepdiff import DeepDiff @@ -123,3 +123,17 @@ def test_datetime_within_array_with_timezone_diff(self): assert not DeepDiff(d1, d2) assert not DeepDiff(d1, d2, ignore_order=True) assert not DeepDiff(d1, d2, truncate_datetime='second') + + def test_truncate_datetime_with_date_and_timedelta(self): + """truncate_datetime must not be applied to types that cannot be truncated.""" + for truncate_datetime in ('second', 'minute', 'hour', 'day'): + d1 = {"a": date(2020, 5, 17)} + d2 = {"a": date(2020, 5, 17)} + assert not DeepDiff(d1, d2, truncate_datetime=truncate_datetime) + + d2 = {"a": date(2020, 5, 18)} + assert DeepDiff(d1, d2, truncate_datetime=truncate_datetime) + + d1 = {"a": timedelta(days=1)} + d2 = {"a": timedelta(days=2)} + assert DeepDiff(d1, d2, truncate_datetime=truncate_datetime)