Datetime naive locali e UTC mescolati nello stesso DB #42
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
FILE: src/backend/services/measurement_service.py (
datetime.now()), src/backend/services/production_service.py:40 (datetime.now()), src/backend/services/auth_service.py:74 (utcnow()),func.now()di MySQL sumeasured_at.COSA: fusi diversi nelle colonne dello stesso DB; i filtri data della dashboard partono naive dal browser (src/frontend/flask_app/templates/statistics/dashboard.html:315-316): con DB in UTC e browser in CET le misure fra 00:00 e 02:00 cadono nel giorno sbagliato.
PERCHÉ NON È STATO CHIUSO IN #36: uniformare richiede una migrazione dei dati esistenti e una decisione (tutto UTC).
PRESUNTO: il fuso del container MySQL in produzione non è stato verificato.
ORIGINE: residui dichiarati alla chiusura delle issue della revisione del 21/09/2026.
ESITO: richiesta
RIF: gitea:Adriano/TieMeasureFlow#42
COSA: analisi (passo 1). Decisione di Adriano del 06/10/2026: tutto UTC nel DB, conversione in ora italiana solo alla presentazione.
STATO MISURATO: docker-compose.yml e docker-compose.dev.yml non impostano TZ; mysql:8.0 e python-slim partono in UTC. In produzione, quindi, sia func.now() sia datetime.now() scrivono già UTC.
Il difetto vero è la presentazione: il backend serializza date naive senza fuso, e new Date("...T08:00:00") nel browser le legge come ora locale (2 ore di errore in CEST). I filtri della dashboard (statistics/dashboard.html:315) mandano ora locale naive.
In sviluppo (uv run sul PC) datetime.now() è locale mentre CURRENT_TIMESTAMP di SQLite è UTC: lì il mescolamento c'è davvero.
MIGRAZIONE DATI: nessuna. PRESUNTO: i dati esistenti, scritti dentro i container, sono già UTC. Se esiste un'installazione con TZ locale sul container, va spostata a mano una volta.
CONTRATTO fra le due unità: ogni datetime in uscita dalle API è ISO 8601 con fuso UTC esplicito (es. "2026-10-06T08:00:00+00:00"); ogni datetime in ingresso con fuso viene convertito in UTC naive; un ingresso naive si intende UTC.
UNITÀ A (backend):
UNITÀ B (frontend Flask):
TEST A: utcnow naive; una risposta con un datetime ha +00:00; date_from con fuso (+02:00) filtra come il suo equivalente UTC; generated_at del report in ora italiana.
TEST B: local_dt("2026-10-06T08:00:00+00:00") → "06/10/2026 10:00"; il test della dashboard, se esiste, controlla i parametri inviati.
NON TOCCARE: schema DB (DateTime naive resta); le migrazioni.
FATTO SE: uv run pytest verde; grep "datetime.now()|utcnow()" in src/backend fuori da utils/tempo.py e dai test → vuoto.
⚡ jeeg — preso in carico 2026-10-06T09:37:16Z
ramo:
lavoro/jeeg· capacità: docker, gpu, systemdESITO: richiesta
COSA: nota all'analisi dopo #41: auth_service.py ha già un utcnow() (commit
35f4692). L'unità A lo sposta in src/backend/utils/tempo.py e lo importa da lì (middleware api_key compreso).Soluzione
ESITO: fatto
RIF: gitea:Adriano/TieMeasureFlow#42
COSA: UTC nel DB e nelle API (ISO +00:00), ora italiana (Europe/Rome) solo in presentazione.
FILE: src/backend/utils/tempo.py — utcnow, as_utc_naive, to_utc_aware, iso_utc, to_local (settings.display_timezone)
FILE: src/backend/models/api/tipi.py — UtcDateTime (serializza +00:00) su tutti gli schemi di risposta; UtcNaiveInput sui 16 parametri Query datetime (aware → UTC naive)
FILE: docker-compose*.yml — MySQL --default-time-zone=+00:00
FILE: src/backend/services/report_service.py — generated_at/measured_at e filtri From/To in ora italiana (_giorno_locale); CSV in UTC ISO
FILE: src/backend/api/routers/setup.py — created_at/last_login via iso_utc
FILE: src/frontend/flask_app/app.py — filtro Jinja local_dt (naive = UTC, None → -), config DISPLAY_TIMEZONE; task_complete.html, dashboard.html (date_from/date_to come istanti UTC del giorno locale), csv-export.js (nome file data locale)
COMMIT:
486e128,7ac291b,a829bf3su V3.0.0PROVA: uv run pytest -q -p no:cacheprovider → 660 passed, 4 skipped
PRESUNTO: nessuna migrazione dati; i container di produzione giravano già in UTC, quindi i dati esistenti sono già UTC naive.
MANCA: vision_worker convert("L") su immagini 16 bit, aperto da #43.