From b29aa7b3a02ecdccc11d216b15f833e76402e0a2 Mon Sep 17 00:00:00 2001 From: Noethix55555 <277300782+Noethix55555@users.noreply.github.com> Date: Sat, 13 Jun 2026 17:26:13 -0400 Subject: [PATCH] fix: decode negative xsd:duration as seconds, not days The PT- workaround passed total_seconds() into timedelta's positional days argument, so PT-30S decoded as -30 days instead of -30 seconds (off by 86400). Pass it as seconds=. --- src/zeep/xsd/types/builtins.py | 2 +- tests/test_xsd_builtins.py | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/zeep/xsd/types/builtins.py b/src/zeep/xsd/types/builtins.py index 8c5c6ba1..8f6f185f 100644 --- a/src/zeep/xsd/types/builtins.py +++ b/src/zeep/xsd/types/builtins.py @@ -136,7 +136,7 @@ def pythonvalue(self, value): if value.startswith("PT-"): value = value.replace("PT-", "PT") result = isodate.parse_duration(value) - return datetime.timedelta(0 - result.total_seconds()) + return datetime.timedelta(seconds=0 - result.total_seconds()) else: return isodate.parse_duration(value) diff --git a/tests/test_xsd_builtins.py b/tests/test_xsd_builtins.py index 4f055da9..41137e01 100644 --- a/tests/test_xsd_builtins.py +++ b/tests/test_xsd_builtins.py @@ -153,6 +153,11 @@ def test_pythonvalue(self): value = "\r \nP0Y1347M0D\t " assert instance.pythonvalue(value) == expected + def test_pythonvalue_negative(self): + instance = builtins.Duration() + assert instance.pythonvalue("PT-30S") == datetime.timedelta(seconds=-30) + assert instance.pythonvalue("PT-1M") == datetime.timedelta(minutes=-1) + class TestDateTime: def test_xmlvalue(self):