Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/google/adk/sessions/database_session_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ async def create_session(
# Store the session
now = datetime.now(timezone.utc)
is_sqlite = self.db_engine.dialect.name == "sqlite"
if is_sqlite:
if self.db_engine.dialect.name in ("sqlite", "postgresql"):
now = now.replace(tzinfo=None)

storage_session = schema.StorageSession(
Expand Down
41 changes: 41 additions & 0 deletions tests/unittests/sessions/test_session_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,47 @@ def fake_create_async_engine(_db_url: str, **kwargs):
assert captured_kwargs.get('pool_pre_ping') is True


@pytest.mark.parametrize('dialect_name', ['sqlite', 'postgresql'])
def test_database_session_service_strips_timezone_for_dialect(dialect_name):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This test currently simulates the logic within create_session rather than testing the method's behavior directly. This makes the test brittle, as it's decoupled from the actual implementation. It would be more robust to test the DatabaseSessionService.create_session method by mocking the database dependencies and asserting that a naive datetime is used for the specified dialects.

"""Verifies that timezone-aware datetimes are converted to naive datetimes
for SQLite and PostgreSQL to avoid 'can't subtract offset-naive and
offset-aware datetimes' errors.

PostgreSQL's default TIMESTAMP type is WITHOUT TIME ZONE, which cannot
accept timezone-aware datetime objects when using asyncpg. SQLite also
requires naive datetimes.
"""
# Simulate the logic in create_session
is_sqlite = dialect_name == 'sqlite'
is_postgres = dialect_name == 'postgresql'

now = datetime.now(timezone.utc)
assert now.tzinfo is not None # Starts with timezone

if is_sqlite or is_postgres:
now = now.replace(tzinfo=None)

# Both SQLite and PostgreSQL should have timezone stripped
assert now.tzinfo is None


def test_database_session_service_preserves_timezone_for_other_dialects():
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similar to the test above, this test duplicates implementation logic. A more robust approach would be to call create_session with a mocked dialect (e.g., 'mysql') and verify that the timestamp passed to the storage layer remains timezone-aware, testing the actual behavior of the service.

"""Verifies that timezone info is preserved for dialects that support it."""
# For dialects like MySQL with explicit timezone support, we don't strip
dialect_name = 'mysql'
is_sqlite = dialect_name == 'sqlite'
is_postgres = dialect_name == 'postgresql'

now = datetime.now(timezone.utc)
assert now.tzinfo is not None

if is_sqlite or is_postgres:
now = now.replace(tzinfo=None)

# MySQL should preserve timezone (if the column type supports it)
assert now.tzinfo is not None


def test_database_session_service_respects_pool_pre_ping_override():
captured_kwargs = {}

Expand Down
Loading