From 29817c3b342b4277b86ec41f0187860112af8035 Mon Sep 17 00:00:00 2001 From: Gao Mingfei Date: Wed, 8 Apr 2026 16:28:00 +0800 Subject: [PATCH] fix(backend): use timezone-aware UTC in memory modules (fix pytest DeprecationWarnings) (#1992) * fix(backend): use timezone-aware UTC in memory modules Replace datetime.utcnow() with datetime.now(timezone.utc) and a shared utc_now_iso_z() helper so persisted ISO timestamps keep the trailing Z suffix without triggering Python 3.12+ deprecation warnings. Made-with: Cursor * refactor(backend): use removesuffix for utc_now_iso_z suffix Makes the +00:00 -> Z transform explicit for the trailing offset only (Copilot review on PR #1992). Made-with: Cursor * style(backend): satisfy ruff UP017 with datetime.UTC in memory queue Made-with: Cursor --------- Co-authored-by: Willem Jiang --- .../packages/harness/deerflow/agents/memory/queue.py | 4 ++-- .../harness/deerflow/agents/memory/storage.py | 11 ++++++++--- .../harness/deerflow/agents/memory/updater.py | 11 +++++++---- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/backend/packages/harness/deerflow/agents/memory/queue.py b/backend/packages/harness/deerflow/agents/memory/queue.py index d78c643f8..1db8c63dc 100644 --- a/backend/packages/harness/deerflow/agents/memory/queue.py +++ b/backend/packages/harness/deerflow/agents/memory/queue.py @@ -4,7 +4,7 @@ import logging import threading import time from dataclasses import dataclass, field -from datetime import datetime +from datetime import UTC, datetime from typing import Any from deerflow.config.memory_config import get_memory_config @@ -18,7 +18,7 @@ class ConversationContext: thread_id: str messages: list[Any] - timestamp: datetime = field(default_factory=datetime.utcnow) + timestamp: datetime = field(default_factory=lambda: datetime.now(UTC)) agent_name: str | None = None correction_detected: bool = False reinforcement_detected: bool = False diff --git a/backend/packages/harness/deerflow/agents/memory/storage.py b/backend/packages/harness/deerflow/agents/memory/storage.py index ba941a7a4..3d57d059b 100644 --- a/backend/packages/harness/deerflow/agents/memory/storage.py +++ b/backend/packages/harness/deerflow/agents/memory/storage.py @@ -4,7 +4,7 @@ import abc import json import logging import threading -from datetime import datetime +from datetime import UTC, datetime from pathlib import Path from typing import Any @@ -15,11 +15,16 @@ from deerflow.config.paths import get_paths logger = logging.getLogger(__name__) +def utc_now_iso_z() -> str: + """Current UTC time as ISO-8601 with ``Z`` suffix (matches prior naive-UTC output).""" + return datetime.now(UTC).isoformat().removesuffix("+00:00") + "Z" + + def create_empty_memory() -> dict[str, Any]: """Create an empty memory structure.""" return { "version": "1.0", - "lastUpdated": datetime.utcnow().isoformat() + "Z", + "lastUpdated": utc_now_iso_z(), "user": { "workContext": {"summary": "", "updatedAt": ""}, "personalContext": {"summary": "", "updatedAt": ""}, @@ -137,7 +142,7 @@ class FileMemoryStorage(MemoryStorage): try: file_path.parent.mkdir(parents=True, exist_ok=True) - memory_data["lastUpdated"] = datetime.utcnow().isoformat() + "Z" + memory_data["lastUpdated"] = utc_now_iso_z() temp_path = file_path.with_suffix(".tmp") with open(temp_path, "w", encoding="utf-8") as f: diff --git a/backend/packages/harness/deerflow/agents/memory/updater.py b/backend/packages/harness/deerflow/agents/memory/updater.py index 5f459b47a..d1f124d4c 100644 --- a/backend/packages/harness/deerflow/agents/memory/updater.py +++ b/backend/packages/harness/deerflow/agents/memory/updater.py @@ -5,14 +5,17 @@ import logging import math import re import uuid -from datetime import datetime from typing import Any from deerflow.agents.memory.prompt import ( MEMORY_UPDATE_PROMPT, format_conversation_for_update, ) -from deerflow.agents.memory.storage import create_empty_memory, get_memory_storage +from deerflow.agents.memory.storage import ( + create_empty_memory, + get_memory_storage, + utc_now_iso_z, +) from deerflow.config.memory_config import get_memory_config from deerflow.models import create_chat_model @@ -86,7 +89,7 @@ def create_memory_fact( normalized_category = category.strip() or "context" validated_confidence = _validate_confidence(confidence) - now = datetime.utcnow().isoformat() + "Z" + now = utc_now_iso_z() memory_data = get_memory_data(agent_name) updated_memory = dict(memory_data) facts = list(memory_data.get("facts", [])) @@ -376,7 +379,7 @@ class MemoryUpdater: Updated memory data. """ config = get_memory_config() - now = datetime.utcnow().isoformat() + "Z" + now = utc_now_iso_z() # Update user sections user_updates = update_data.get("user", {})