You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tooling.apache.org by sb...@apache.org on 2026/09/28 16:25:20 UTC
(tooling-trusted-releases) branch sbp updated: Preserve timezone information across models
This is an automated email from the ASF dual-hosted git repository.
sbp pushed a commit to branch sbp
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-releases.git
The following commit(s) were added to refs/heads/sbp by this push:
new 191367f7 Preserve timezone information across models
191367f7 is described below
commit 191367f72cf7dd34b50288d4292fa7fbf15e6c23
Author: Sean B. Palmer <se...@miscoranda.com>
AuthorDate: Mon Sep 28 17:24:28 2026 +0100
Preserve timezone information across models
---
atr/models/sql.py | 24 ++++++++++----------
tests/unit/test_model_datetimes.py | 46 ++++++++++++++++++++++++++++++++++++++
2 files changed, 58 insertions(+), 12 deletions(-)
diff --git a/atr/models/sql.py b/atr/models/sql.py
index 193f785d..d70007d0 100644
--- a/atr/models/sql.py
+++ b/atr/models/sql.py
@@ -911,13 +911,13 @@ class Task(sqlmodel.SQLModel, table=True):
self.status = TaskStatus(self.status)
if isinstance(self.added, str):
- self.added = datetime.datetime.fromisoformat(self.added.rstrip("Z"))
+ self.added = datetime.datetime.fromisoformat(self.added)
if isinstance(self.started, str):
- self.started = datetime.datetime.fromisoformat(self.started.rstrip("Z"))
+ self.started = datetime.datetime.fromisoformat(self.started)
if isinstance(self.completed, str):
- self.completed = datetime.datetime.fromisoformat(self.completed.rstrip("Z"))
+ self.completed = datetime.datetime.fromisoformat(self.completed)
if isinstance(self.result, dict):
self.result = results.ResultsAdapter.validate_python(self.result)
@@ -1803,7 +1803,7 @@ class Release(sqlmodel.SQLModel, table=True):
for name in ("activity_at", "archived", "created", "released", "vote_resolved", "vote_started"):
value = getattr(self, name)
if isinstance(value, str):
- setattr(self, name, datetime.datetime.fromisoformat(value.rstrip("Z")))
+ setattr(self, name, datetime.datetime.fromisoformat(value))
if isinstance(self.phase, str):
self.phase = ReleasePhase(self.phase)
@@ -1939,7 +1939,7 @@ class BallotPaper(sqlmodel.SQLModel, table=True):
self.choice = VoteChoice(self.choice)
if isinstance(self.created, str):
- self.created = datetime.datetime.fromisoformat(self.created.rstrip("Z"))
+ self.created = datetime.datetime.fromisoformat(self.created)
@property
def safe_revision_number_at_cast(self) -> safe.RevisionNumber:
@@ -2020,7 +2020,7 @@ class CheckResultIgnore(sqlmodel.SQLModel, table=True):
def model_post_init(self, _context):
if isinstance(self.created, str):
- self.created = datetime.datetime.fromisoformat(self.created.rstrip("Z"))
+ self.created = datetime.datetime.fromisoformat(self.created)
# Distribution: Release
@@ -2128,7 +2128,7 @@ class SigningCertificate(sqlmodel.SQLModel, table=True):
def model_post_init(self, _context):
if isinstance(self.latest_self_signature, str):
- self.latest_self_signature = datetime.datetime.fromisoformat(self.latest_self_signature.rstrip("Z"))
+ self.latest_self_signature = datetime.datetime.fromisoformat(self.latest_self_signature)
# SigningKey: SigningCertificate
@@ -2168,10 +2168,10 @@ class SigningKey(sqlmodel.SQLModel, table=True):
def model_post_init(self, _context):
if isinstance(self.created, str):
- self.created = datetime.datetime.fromisoformat(self.created.rstrip("Z"))
+ self.created = datetime.datetime.fromisoformat(self.created)
if isinstance(self.expires, str):
- self.expires = datetime.datetime.fromisoformat(self.expires.rstrip("Z"))
+ self.expires = datetime.datetime.fromisoformat(self.expires)
# Quarantined: Release
@@ -2212,10 +2212,10 @@ class Quarantined(sqlmodel.SQLModel, table=True):
def model_post_init(self, _context):
if isinstance(self.created, str):
- self.created = datetime.datetime.fromisoformat(self.created.rstrip("Z"))
+ self.created = datetime.datetime.fromisoformat(self.created)
if isinstance(self.completed, str):
- self.completed = datetime.datetime.fromisoformat(self.completed.rstrip("Z"))
+ self.completed = datetime.datetime.fromisoformat(self.completed)
if isinstance(self.status, str):
self.status = QuarantineStatus(self.status)
@@ -2446,7 +2446,7 @@ class Revision(sqlmodel.SQLModel, table=True):
def model_post_init(self, _context):
if isinstance(self.created, str):
- self.created = datetime.datetime.fromisoformat(self.created.rstrip("Z"))
+ self.created = datetime.datetime.fromisoformat(self.created)
if isinstance(self.phase, str):
self.phase = ReleasePhase(self.phase)
diff --git a/tests/unit/test_model_datetimes.py b/tests/unit/test_model_datetimes.py
new file mode 100644
index 00000000..8bc72e42
--- /dev/null
+++ b/tests/unit/test_model_datetimes.py
@@ -0,0 +1,46 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import datetime
+
+import pytest
+import sqlmodel
+
+import atr.models.sql as sql
+
+
+@pytest.mark.parametrize(
+ ("model", "fields"),
+ [
+ (sql.BallotPaper, ("created",)),
+ (sql.CheckResultIgnore, ("created",)),
+ (sql.Quarantined, ("created", "completed")),
+ (sql.Release, ("activity_at", "archived", "created", "released", "vote_resolved", "vote_started")),
+ (sql.Revision, ("created",)),
+ (sql.SigningCertificate, ("latest_self_signature",)),
+ (sql.SigningKey, ("created", "expires")),
+ (sql.Task, ("added", "started", "completed")),
+ ],
+)
+@pytest.mark.parametrize("timestamp", ["2026-09-28T12:34:56.123456Z", "2026-09-28T14:34:56.123456+02:00"])
+def test_model_datetime_strings_preserve_timezone(
+ model: type[sqlmodel.SQLModel], fields: tuple[str, ...], timestamp: str
+) -> None:
+ record = model(**dict.fromkeys(fields, timestamp))
+ expected = datetime.datetime(2026, 9, 28, 12, 34, 56, 123456, tzinfo=datetime.UTC)
+ for field in fields:
+ assert getattr(record, field) == expected
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@tooling.apache.org
For additional commands, e-mail: commits-help@tooling.apache.org