replace hardcoded US/Pacific timezone references with timezone.utc (#4404)

Co-authored-by: kartik-mem0 <kartik.labhshetwar@mem0.ai>
This commit is contained in:
Anisha Mahuli
2026-03-19 17:29:29 +05:30
committed by GitHub
co-authored by kartik-mem0
parent 46b4b2e9c8
commit 08de18f860
5 changed files with 152 additions and 38 deletions
+5 -6
View File
@@ -1,7 +1,6 @@
import logging
import uuid
from datetime import datetime
import pytz
from datetime import datetime, timezone
from .base import NeptuneBase
@@ -114,7 +113,7 @@ class MemoryGraph(NeptuneBase):
"name": destination,
"type": destination_type,
"user_id": user_id,
"created_at": datetime.now(pytz.timezone("US/Pacific")).isoformat(),
"created_at": datetime.now(timezone.utc).isoformat(),
}
self.vector_store.insert(
vectors=[dest_embedding],
@@ -189,7 +188,7 @@ class MemoryGraph(NeptuneBase):
"name": source,
"type": source_type,
"user_id": user_id,
"created_at": datetime.now(pytz.timezone("US/Pacific")).isoformat(),
"created_at": datetime.now(timezone.utc).isoformat(),
}
self.vector_store.insert(
vectors=[source_embedding],
@@ -316,14 +315,14 @@ class MemoryGraph(NeptuneBase):
"name": source,
"type": source_type,
"user_id": user_id,
"created_at": datetime.now(pytz.timezone("US/Pacific")).isoformat(),
"created_at": datetime.now(timezone.utc).isoformat(),
}
destination_id = str(uuid.uuid4())
destination_payload = {
"name": destination,
"type": destination_type,
"user_id": user_id,
"created_at": datetime.now(pytz.timezone("US/Pacific")).isoformat(),
"created_at": datetime.now(timezone.utc).isoformat(),
}
self.vector_store.insert(
vectors=[source_embedding, dest_embedding],
+40 -22
View File
@@ -8,10 +8,9 @@ import os
import uuid
import warnings
from copy import deepcopy
from datetime import datetime
from datetime import datetime, timezone
from typing import Any, Dict, Optional
import pytz
from pydantic import ValidationError
from mem0.configs.base import MemoryConfig, MemoryItem
@@ -51,6 +50,19 @@ warnings.filterwarnings("ignore", category=DeprecationWarning, message=".*swigva
logger = logging.getLogger(__name__)
def _normalize_iso_timestamp_to_utc(timestamp: Optional[str]) -> Optional[str]:
"""Normalize timezone-aware ISO timestamps to UTC without rewriting naive values."""
if not timestamp:
return timestamp
try:
parsed = datetime.fromisoformat(timestamp)
except ValueError:
return timestamp
if parsed.tzinfo is None:
return timestamp
return parsed.astimezone(timezone.utc).isoformat()
# Fields that hold runtime auth/connection objects and must be preserved.
# These are non-serializable objects (e.g. AWSV4SignerAuth, RequestsHttpConnection)
# needed by clients like OpenSearch — not sensitive strings to redact.
@@ -637,7 +649,10 @@ class Memory(MemoryBase):
updated_metadata["agent_id"] = metadata["agent_id"]
if metadata.get("run_id"):
updated_metadata["run_id"] = metadata["run_id"]
updated_metadata["updated_at"] = datetime.now(pytz.timezone("US/Pacific")).isoformat()
updated_metadata["created_at"] = _normalize_iso_timestamp_to_utc(
updated_metadata.get("created_at")
)
updated_metadata["updated_at"] = datetime.now(timezone.utc).isoformat()
self.vector_store.update(
vector_id=memory_id,
@@ -700,8 +715,8 @@ class Memory(MemoryBase):
id=memory.id,
memory=memory.payload.get("data", ""),
hash=memory.payload.get("hash"),
created_at=memory.payload.get("created_at"),
updated_at=memory.payload.get("updated_at"),
created_at=_normalize_iso_timestamp_to_utc(memory.payload.get("created_at")),
updated_at=_normalize_iso_timestamp_to_utc(memory.payload.get("updated_at")),
).model_dump()
for key in promoted_payload_keys:
@@ -803,8 +818,8 @@ class Memory(MemoryBase):
id=mem.id,
memory=mem.payload.get("data", ""),
hash=mem.payload.get("hash"),
created_at=mem.payload.get("created_at"),
updated_at=mem.payload.get("updated_at"),
created_at=_normalize_iso_timestamp_to_utc(mem.payload.get("created_at")),
updated_at=_normalize_iso_timestamp_to_utc(mem.payload.get("updated_at")),
).model_dump(exclude={"score"})
for key in promoted_payload_keys:
@@ -1035,8 +1050,8 @@ class Memory(MemoryBase):
id=mem.id,
memory=mem.payload.get("data", ""),
hash=mem.payload.get("hash"),
created_at=mem.payload.get("created_at"),
updated_at=mem.payload.get("updated_at"),
created_at=_normalize_iso_timestamp_to_utc(mem.payload.get("created_at")),
updated_at=_normalize_iso_timestamp_to_utc(mem.payload.get("updated_at")),
score=mem.score,
).model_dump()
@@ -1145,7 +1160,7 @@ class Memory(MemoryBase):
metadata = metadata or {}
metadata["data"] = data
metadata["hash"] = hashlib.md5(data.encode()).hexdigest()
metadata["created_at"] = datetime.now(pytz.timezone("US/Pacific")).isoformat()
metadata["created_at"] = datetime.now(timezone.utc).isoformat()
self.vector_store.insert(
vectors=[embeddings],
@@ -1217,8 +1232,8 @@ class Memory(MemoryBase):
new_metadata["data"] = data
new_metadata["hash"] = hashlib.md5(data.encode()).hexdigest()
new_metadata["created_at"] = existing_memory.payload.get("created_at")
new_metadata["updated_at"] = datetime.now(pytz.timezone("US/Pacific")).isoformat()
new_metadata["created_at"] = _normalize_iso_timestamp_to_utc(existing_memory.payload.get("created_at"))
new_metadata["updated_at"] = datetime.now(timezone.utc).isoformat()
# Preserve session identifiers from existing memory only if not provided in new metadata
if "user_id" not in new_metadata and "user_id" in existing_memory.payload:
@@ -1661,7 +1676,10 @@ class AsyncMemory(MemoryBase):
updated_metadata["agent_id"] = meta["agent_id"]
if meta.get("run_id"):
updated_metadata["run_id"] = meta["run_id"]
updated_metadata["updated_at"] = datetime.now(pytz.timezone("US/Pacific")).isoformat()
updated_metadata["created_at"] = _normalize_iso_timestamp_to_utc(
updated_metadata.get("created_at")
)
updated_metadata["updated_at"] = datetime.now(timezone.utc).isoformat()
await asyncio.to_thread(
self.vector_store.update,
@@ -1747,8 +1765,8 @@ class AsyncMemory(MemoryBase):
id=memory.id,
memory=memory.payload.get("data", ""),
hash=memory.payload.get("hash"),
created_at=memory.payload.get("created_at"),
updated_at=memory.payload.get("updated_at"),
created_at=_normalize_iso_timestamp_to_utc(memory.payload.get("created_at")),
updated_at=_normalize_iso_timestamp_to_utc(memory.payload.get("updated_at")),
).model_dump()
for key in promoted_payload_keys:
@@ -1855,8 +1873,8 @@ class AsyncMemory(MemoryBase):
id=mem.id,
memory=mem.payload.get("data", ""),
hash=mem.payload.get("hash"),
created_at=mem.payload.get("created_at"),
updated_at=mem.payload.get("updated_at"),
created_at=_normalize_iso_timestamp_to_utc(mem.payload.get("created_at")),
updated_at=_normalize_iso_timestamp_to_utc(mem.payload.get("updated_at")),
).model_dump(exclude={"score"})
for key in promoted_payload_keys:
@@ -2096,8 +2114,8 @@ class AsyncMemory(MemoryBase):
id=mem.id,
memory=mem.payload.get("data", ""),
hash=mem.payload.get("hash"),
created_at=mem.payload.get("created_at"),
updated_at=mem.payload.get("updated_at"),
created_at=_normalize_iso_timestamp_to_utc(mem.payload.get("created_at")),
updated_at=_normalize_iso_timestamp_to_utc(mem.payload.get("updated_at")),
score=mem.score,
).model_dump()
@@ -2211,7 +2229,7 @@ class AsyncMemory(MemoryBase):
metadata = metadata or {}
metadata["data"] = data
metadata["hash"] = hashlib.md5(data.encode()).hexdigest()
metadata["created_at"] = datetime.now(pytz.timezone("US/Pacific")).isoformat()
metadata["created_at"] = datetime.now(timezone.utc).isoformat()
await asyncio.to_thread(
self.vector_store.insert,
@@ -2301,8 +2319,8 @@ class AsyncMemory(MemoryBase):
new_metadata["data"] = data
new_metadata["hash"] = hashlib.md5(data.encode()).hexdigest()
new_metadata["created_at"] = existing_memory.payload.get("created_at")
new_metadata["updated_at"] = datetime.now(pytz.timezone("US/Pacific")).isoformat()
new_metadata["created_at"] = _normalize_iso_timestamp_to_utc(existing_memory.payload.get("created_at"))
new_metadata["updated_at"] = datetime.now(timezone.utc).isoformat()
# Preserve session identifiers from existing memory only if not provided in new metadata
if "user_id" not in new_metadata and "user_id" in existing_memory.payload:
+7 -8
View File
@@ -1,10 +1,9 @@
import json
import logging
from datetime import datetime
from datetime import datetime, timezone
from functools import reduce
import numpy as np
import pytz
import redis
from redis.commands.search.query import Query
from redisvl.index import SearchIndex
@@ -164,12 +163,12 @@ class RedisDB(VectorStoreBase):
"hash": result["hash"],
"data": result["memory"],
"created_at": datetime.fromtimestamp(
int(result["created_at"]), tz=pytz.timezone("US/Pacific")
int(result["created_at"]), tz=timezone.utc
).isoformat(timespec="microseconds"),
**(
{
"updated_at": datetime.fromtimestamp(
int(result["updated_at"]), tz=pytz.timezone("US/Pacific")
int(result["updated_at"]), tz=timezone.utc
).isoformat(timespec="microseconds")
}
if "updated_at" in result
@@ -207,13 +206,13 @@ class RedisDB(VectorStoreBase):
payload = {
"hash": result["hash"],
"data": result["memory"],
"created_at": datetime.fromtimestamp(int(result["created_at"]), tz=pytz.timezone("US/Pacific")).isoformat(
"created_at": datetime.fromtimestamp(int(result["created_at"]), tz=timezone.utc).isoformat(
timespec="microseconds"
),
**(
{
"updated_at": datetime.fromtimestamp(
int(result["updated_at"]), tz=pytz.timezone("US/Pacific")
int(result["updated_at"]), tz=timezone.utc
).isoformat(timespec="microseconds")
}
if "updated_at" in result
@@ -271,12 +270,12 @@ class RedisDB(VectorStoreBase):
"hash": result["hash"],
"data": result["memory"],
"created_at": datetime.fromtimestamp(
int(result["created_at"]), tz=pytz.timezone("US/Pacific")
int(result["created_at"]), tz=timezone.utc
).isoformat(timespec="microseconds"),
**(
{
"updated_at": datetime.fromtimestamp(
int(result["updated_at"]), tz=pytz.timezone("US/Pacific")
int(result["updated_at"]), tz=timezone.utc
).isoformat(timespec="microseconds")
}
if result.__dict__.get("updated_at")