From 383bdb631223c701527de02a2d6d7beb719e186f Mon Sep 17 00:00:00 2001 From: Djuri Baars Date: Tue, 20 Jan 2026 16:26:02 +0100 Subject: [PATCH] [fix] Fix missing timezone information --- lnbits/db.py | 9 +++++++-- tests/unit/test_db.py | 23 ++++++++++++++++++++++- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/lnbits/db.py b/lnbits/db.py index 8b4389297..f13dc4a35 100644 --- a/lnbits/db.py +++ b/lnbits/db.py @@ -337,7 +337,8 @@ class Database(Compat): f = "%Y-%m-%d %H:%M:%S.%f" if "." not in value: f = "%Y-%m-%d %H:%M:%S" - return datetime.strptime(value, f) + # Parse and add UTC timezone info + return datetime.strptime(value, f).replace(tzinfo=timezone.utc) dbapi_connection.run_async( lambda connection: connection.set_type_codec( @@ -756,7 +757,11 @@ def dict_to_model(_row: dict, model: type[TModel]) -> TModel: # noqa: C901 if DB_TYPE == SQLITE: _dict[key] = datetime.fromtimestamp(value, timezone.utc) else: - _dict[key] = value + # Ensure PostgreSQL datetime values have timezone info + if isinstance(value, datetime) and value.tzinfo is None: + _dict[key] = value.replace(tzinfo=timezone.utc) + else: + _dict[key] = value continue if issubclass(type_, BaseModel): _dict[key] = dict_to_submodel(type_, value) diff --git a/tests/unit/test_db.py b/tests/unit/test_db.py index 98e7ba328..94b4239f7 100644 --- a/tests/unit/test_db.py +++ b/tests/unit/test_db.py @@ -1,4 +1,4 @@ -from datetime import date +from datetime import date, timezone import pytest @@ -8,6 +8,9 @@ from lnbits.core.crud import ( get_wallet, get_wallet_for_key, ) +from lnbits.core.crud.payments import get_payment +from lnbits.core.models import CreateInvoice +from lnbits.core.services.payments import create_wallet_invoice from lnbits.db import POSTGRES @@ -18,6 +21,24 @@ async def test_date_conversion(db): assert row and isinstance(row.get("now"), date) +@pytest.mark.anyio +async def test_payment_datetime_fields_have_timezone(app, to_user): + """Test that Payment datetime fields always have UTC timezone info.""" + wallet = await create_wallet(user_id=to_user.id, wallet_name="test_tz_wallet") + invoice_data = CreateInvoice(amount=10, memo="timezone_test", out=False) + invoice = await create_wallet_invoice(wallet.id, invoice_data) + + payment = await get_payment(invoice.checking_id) + assert payment is not None + + # All datetime fields should have UTC timezone info + assert payment.time.tzinfo == timezone.utc + assert payment.created_at.tzinfo == timezone.utc + assert payment.updated_at.tzinfo == timezone.utc + if payment.expiry: + assert payment.expiry.tzinfo == timezone.utc + + # make test to create wallet and delete wallet @pytest.mark.anyio async def test_create_wallet_and_delete_wallet(app, to_user):