From 012e50e3edb41ca6eb58e7d5554f7b5e13747e99 Mon Sep 17 00:00:00 2001 From: Peter Bieringer Date: Sun, 2 Nov 2025 18:33:04 +0100 Subject: [PATCH 1/3] add min_unixtime constant --- radicale/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/radicale/utils.py b/radicale/utils.py index f70e38e7..131e4891 100644 --- a/radicale/utils.py +++ b/radicale/utils.py @@ -47,8 +47,9 @@ ADDRESS_TYPE = Union[Tuple[Union[str, bytes, bytearray], int], Tuple[str, int, int, int]] -# Max YEAR in datetime in unixtime +# Max/Min YEAR in datetime in unixtime DATETIME_MAX_UNIXTIME: int = (datetime.MAXYEAR - 1970) * 365 * 24 * 60 * 60 +DATETIME_MIN_UNIXTIME: int = (datetime.MINYEAR - 1970) * 365 * 24 * 60 * 60 def load_plugin(internal_types: Sequence[str], module_name: str, From bd1497ca15786b4a78807e9ac27b8d13677610eb Mon Sep 17 00:00:00 2001 From: Peter Bieringer Date: Sun, 2 Nov 2025 18:33:28 +0100 Subject: [PATCH 2/3] catch min/max to avoid issues on 32-bit systems --- radicale/utils.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/radicale/utils.py b/radicale/utils.py index 131e4891..ba5c69ff 100644 --- a/radicale/utils.py +++ b/radicale/utils.py @@ -280,9 +280,14 @@ def format_ut(unixtime: int) -> str: if sys.platform == "win32": # TODO check how to support this better return str(unixtime) - if unixtime < DATETIME_MAX_UNIXTIME: - dt = datetime.datetime(1970, 1, 1, tzinfo=datetime.timezone.utc) + datetime.timedelta(seconds=unixtime) - r = str(unixtime) + "(" + dt.strftime('%Y-%m-%dT%H:%M:%SZ') + ")" + if unixtime <= DATETIME_MIN_UNIXTIME: + r = str(unixtime) + "(<=MIN:" + str(DATETIME_MIN_UNIXTIME) + ")" + elif unixtime >= DATETIME_MAX_UNIXTIME: + r = str(unixtime) + "(>=MAX:" + str(DATETIME_MAX_UNIXTIME) + ")" else: - r = str(unixtime) + "(>MAX:" + str(DATETIME_MAX_UNIXTIME) + ")" + if sys.version_info < (3, 11): + dt = datetime.datetime.utcfromtimestamp(unixtime) + else: + dt = datetime.datetime.fromtimestamp(unixtime, datetime.UTC) + r = str(unixtime) + "(" + dt.strftime('%Y-%m-%dT%H:%M:%SZ') + ")" return r From 91a92226ba4985a4ea686abc8da9f7949c147cda Mon Sep 17 00:00:00 2001 From: Peter Bieringer Date: Sun, 2 Nov 2025 18:33:54 +0100 Subject: [PATCH 3/3] changelog for fixing #1904 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 12e5c97e..cde3ad4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Fix: out-of-range timestamp on 32-bit systems * Feature: extend logging with response size in bytes and flag served as plain or gzip * Feature: [storage] strict_preconditions: new config option to enforce strict preconditions check on PUT in case item already exists [RFC6352#9.2] +* Fix: format_ut problem on 32-bit systems ## 3.5.7 * Extend: [auth] dovecot: add support for version >= 2.4