Fixed timezone being returned incorrectly

Happened if you've set TZ to non-UTC.

Apparently astimezone and replace doesn't do the same thing even if tzinfo is None.
This commit is contained in:
Donkie
2023-10-02 21:35:46 +02:00
parent e07436bd8c
commit 205574fa2c
7 changed files with 30 additions and 5 deletions

View File

@@ -13,7 +13,7 @@ from spoolman.math import length_from_weight
def datetime_to_str(dt: datetime) -> str: def datetime_to_str(dt: datetime) -> str:
"""Convert a datetime object to a string.""" """Convert a datetime object to a string."""
if dt.tzinfo is None: if dt.tzinfo is None:
dt = dt.astimezone(tz=timezone.utc) dt = dt.replace(tzinfo=timezone.utc)
return dt.isoformat().replace("+00:00", "Z") return dt.isoformat().replace("+00:00", "Z")

View File

@@ -230,8 +230,8 @@ async def use_weight(db: AsyncSession, spool_id: int, weight: float) -> models.S
spool = await get_by_id(db, spool_id) spool = await get_by_id(db, spool_id)
if spool.first_used is None: if spool.first_used is None:
spool.first_used = datetime.utcnow() spool.first_used = datetime.utcnow().replace(microsecond=0)
spool.last_used = datetime.utcnow() spool.last_used = datetime.utcnow().replace(microsecond=0)
await db.commit() await db.commit()
await spool_changed(spool) await spool_changed(spool)
@@ -275,8 +275,8 @@ async def use_length(db: AsyncSession, spool_id: int, length: float) -> models.S
spool = await get_by_id(db, spool_id) spool = await get_by_id(db, spool_id)
if spool.first_used is None: if spool.first_used is None:
spool.first_used = datetime.utcnow() spool.first_used = datetime.utcnow().replace(microsecond=0)
spool.last_used = datetime.utcnow() spool.last_used = datetime.utcnow().replace(microsecond=0)
await db.commit() await db.commit()
await spool_changed(spool) await spool_changed(spool)

View File

@@ -6,6 +6,7 @@ services:
environment: environment:
- COCKROACH_USER=john - COCKROACH_USER=john
- COCKROACH_DATABASE=spoolman - COCKROACH_DATABASE=spoolman
- TZ=Asia/Seoul
healthcheck: healthcheck:
test: test:
[ [
@@ -26,6 +27,7 @@ services:
- SPOOLMAN_DB_NAME=spoolman - SPOOLMAN_DB_NAME=spoolman
- SPOOLMAN_DB_USERNAME=john - SPOOLMAN_DB_USERNAME=john
- SPOOLMAN_LOGGING_LEVEL=INFO - SPOOLMAN_LOGGING_LEVEL=INFO
- TZ=Europe/Stockholm
depends_on: depends_on:
db: db:
condition: service_healthy condition: service_healthy

View File

@@ -8,6 +8,7 @@ services:
- MARIADB_PASSWORD=abc - MARIADB_PASSWORD=abc
- MARIADB_DATABASE=spoolman - MARIADB_DATABASE=spoolman
- MARIADB_MYSQL_LOCALHOST_USER=true - MARIADB_MYSQL_LOCALHOST_USER=true
- TZ=Asia/Seoul
healthcheck: healthcheck:
test: test:
[ [
@@ -30,6 +31,7 @@ services:
- SPOOLMAN_DB_USERNAME=john - SPOOLMAN_DB_USERNAME=john
- SPOOLMAN_DB_PASSWORD=abc - SPOOLMAN_DB_PASSWORD=abc
- SPOOLMAN_LOGGING_LEVEL=INFO - SPOOLMAN_LOGGING_LEVEL=INFO
- TZ=Europe/Stockholm
depends_on: depends_on:
db: db:
condition: service_healthy condition: service_healthy

View File

@@ -4,6 +4,8 @@ services:
image: postgres:11-alpine image: postgres:11-alpine
environment: environment:
- POSTGRES_PASSWORD=abc - POSTGRES_PASSWORD=abc
- TZ='GMT+4'
- PGTZ='GMT+4'
spoolman: spoolman:
image: donkie/spoolman:test image: donkie/spoolman:test
environment: environment:
@@ -14,6 +16,7 @@ services:
- SPOOLMAN_DB_USERNAME=postgres - SPOOLMAN_DB_USERNAME=postgres
- SPOOLMAN_DB_PASSWORD=abc - SPOOLMAN_DB_PASSWORD=abc
- SPOOLMAN_LOGGING_LEVEL=INFO - SPOOLMAN_LOGGING_LEVEL=INFO
- TZ=Europe/Stockholm
depends_on: depends_on:
- db - db
tester: tester:

View File

@@ -4,6 +4,7 @@ services:
image: donkie/spoolman:test image: donkie/spoolman:test
environment: environment:
- SPOOLMAN_LOGGING_LEVEL=INFO - SPOOLMAN_LOGGING_LEVEL=INFO
- TZ=Europe/Stockholm
tester: tester:
image: donkie/spoolman-tester:latest image: donkie/spoolman-tester:latest
volumes: volumes:

View File

@@ -2,6 +2,7 @@
import asyncio import asyncio
import math import math
from datetime import datetime, timezone
from typing import Any from typing import Any
import httpx import httpx
@@ -41,6 +42,14 @@ def test_use_spool_weight(random_filament: dict[str, Any], use_weight: float):
assert spool["used_weight"] == pytest.approx(max(use_weight, 0)) assert spool["used_weight"] == pytest.approx(max(use_weight, 0))
assert spool["remaining_weight"] == pytest.approx(min(max(start_weight - use_weight, 0), filament_net_weight)) assert spool["remaining_weight"] == pytest.approx(min(max(start_weight - use_weight, 0), filament_net_weight))
# Verify that first_used has been updated
diff = abs((datetime.now(tz=timezone.utc) - datetime.fromisoformat(spool["first_used"])).total_seconds())
assert diff < 60
# Verify that last_used has been updated
diff = abs((datetime.now(tz=timezone.utc) - datetime.fromisoformat(spool["last_used"])).total_seconds())
assert diff < 60
# Clean up # Clean up
httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status() httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status()
@@ -56,6 +65,7 @@ def test_use_spool_length(random_filament: dict[str, Any], use_length: float):
json={ json={
"filament_id": random_filament["id"], "filament_id": random_filament["id"],
"remaining_weight": start_weight, "remaining_weight": start_weight,
"first_used": "2023-01-01T00:00:00Z",
}, },
) )
result.raise_for_status() result.raise_for_status()
@@ -79,6 +89,13 @@ def test_use_spool_length(random_filament: dict[str, Any], use_length: float):
assert spool["used_weight"] == pytest.approx(max(use_weight, 0)) assert spool["used_weight"] == pytest.approx(max(use_weight, 0))
assert spool["remaining_weight"] == pytest.approx(min(max(start_weight - use_weight, 0), filament_net_weight)) assert spool["remaining_weight"] == pytest.approx(min(max(start_weight - use_weight, 0), filament_net_weight))
# Verify that first_used hasn't been updated since it was already set
assert spool["first_used"] == "2023-01-01T00:00:00Z"
# Verify that last_used has been updated
diff = abs((datetime.now(tz=timezone.utc) - datetime.fromisoformat(spool["last_used"])).total_seconds())
assert diff < 60
# Clean up # Clean up
httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status() httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status()