mirror of
https://github.com/skoelle/calender_sync.git
synced 2026-09-17 18:20:24 +00:00
- Add TIMEZONE environment variable support (default: UTC) - Convert naive UTC datetimes from database to local timezone in API responses - Add timezone field to EventResponse and EventsListResponse Pydantic models - Update web template to display timezone information - Update PLAN.md to document timezone changes This fixes the issue where events at 8:00 UTC would appear as 6:00 GMT by displaying times in the correct local timezone.
5.1 KiB
5.1 KiB
PLAN.md - Implementierungsplan
Feature: REST API + Web-Frontend für Calendar Sync
Übersicht
Ziel: FastAPI-basierte API und ein Jinja2 Web-Frontend hinzufügen, um die nächsten 10 Termine aus MariaDB auszulesen und anzuzeigen. Gleicher Docker Build, separater Container.
Phase 1: Projektstruktur + Shared Module
Step 1.1: API-Verzeichnisstruktur anlegen
api/
├── __init__.py
├── main.py
├── database.py
└── templates/
└── index.html
Step 1.2: database.py - DB Connection extrahieren
get_connection()Funktion aussync.py:81-89inapi/database.pyverschieben- Connection Pooling optional (First: einfacher single connection)
- Umgebungsvariablen identisch zu sync.py
- sync.py importiert dann
from api.database import get_connection
Dateien: api/__init__.py, api/database.py, sync.py (Import anpassen)
Phase 2: FastAPI Backend
Step 2.1: api/main.py - FastAPI App erstellen
- FastAPI Instanz erstellen
- GET
/api/eventsEndpoint- Query Parameter:
limit(default 10, max 50),calendar_label(optional),search(optional) - SQL bei search:
WHERE deleted=0 AND start_at >= NOW() AND summary LIKE %s ORDER BY start_at ASC LIMIT %s - SQL ohne search:
WHERE deleted=0 AND start_at >= NOW() ORDER BY start_at ASC LIMIT %s - Response als JSON
- Query Parameter:
- GET
/api/events/{id}Endpoint- Einzelnes Event nach ID
- GET
/api/healthEndpoint- Response:
{"status": "ok"}
- Response:
- GET
/Endpoint- Jinja2 Template rendern mit Events
- Query Parameter
searchweiterleiten
Step 2.2: Response Model definieren
- Pydantic Model für Event Response
- DATETIME → String Konvertierung (ISO Format)
Dateien: api/main.py
Phase 3: Web-Frontend
Step 3.1: api/templates/index.html
- Einfaches HTML5 Template
- Jinja2 Variablen:
{{ events }},{{ search }} - CSS inline oder im
<style>Block - Suchfeld oben (Formular mit GET Parameter
search) - Darstellung:
- Datum + Uhrzeit (oder "Ganztägig")
- Titel (summary)
- Ort (location) - falls vorhanden
- Status Badge (grün=CONFIRMED, gelb=TENTATIVE, rot=CANCELLED)
- Kein JavaScript nötig (nur server-side rendering)
Dateien: api/templates/index.html
Phase 4: Dependencies + Docker
Step 4.1: requirements.txt erweitern
fastapi==0.115.0
uvicorn[standard]==0.30.0
jinja2==3.1.4
Step 4.2: Dockerfile anpassen
COPY api/ ./api/hinzufügen- Standard CMD bleibt
python sync.py
Step 4.3: docker-compose.yml erweitern
calendar-apiService hinzufügen- Gleicher Image
command: ["uvicorn", "api.main:app", "--host", "0.0.0.0", "--port", "8000"]- Port Mapping:
${API_PORT:-8000}:8000 - DB Environment Variablen
- Watchtower Label
Step 4.4: .env.example erweitern
API_PORT=8000hinzufügen
Dateien: requirements.txt, Dockerfile, docker-compose.yml, .env.example
Phase 5: Refactoring sync.py
Step 5.1: sync.py importieren
from api.database import get_connectionverwenden- Lokale
get_connection()Funktion entfernen - Database Bootstrap bleibt in sync.py (gehört nicht zur API)
Zusammenfassung der zu erstellenden Dateien
| Datei | Aktion |
|---|---|
api/__init__.py |
Neu erstellen |
api/database.py |
Neu erstellen |
api/main.py |
Neu erstellen |
api/templates/index.html |
Neu erstellen |
sync.py |
Import anpassen |
requirements.txt |
Erweitern |
Dockerfile |
Erweitern |
docker-compose.yml |
Erweitern |
.env.example |
Erweitern |
Offene Punkte
- Zeitzonen-Korrektur in API und Web-UI (statt GMT → lokaler Zeitzone)
- Notwendigkeit eines timezone-Feldes in der DB für korrekte Speicherung
- Zeitstempel-Speicherung mit korrekter Zeitzone-Feldunterstützung in DB
- DB Bootstrap - bleibt in sync.py
- Template Styling - einfaches CSS, kein Framework
- Search - optionaler Suchbegriff auf Event-Titel (API + Frontend)
Richtig gelöst: Keine DB-Zeitzone-Speicherung nötig
Da MySQL/MariaDB naive DATETIME-Werte speichert (ohne Zeitzone), muss die Zeitzone-Zuweisung auf der API/Web-UI-Seite erfolgen. Dies ist korrekt, da:
- Datenbank-Speicherung: MariaDB DATETIME-Spalten können naive Datetimes speichern (alle in einem Standard)
- Zeitzone-Wiederherstellung: Die API/Frontend-Komponenten können naive Datetimes in die korrekte Benutzer-Zeitzone konvertieren, wenn sie benötigt werden
- Vereinfachte Architektur: Keine komplexe DB-Schema-Änderung erforderlich
Lösung: Konvertieren Sie naive UTC-Daten aus DB → lokale Zeitzone im API/Web-UI durch Hinzufügen von timezone-Feld in Response-Modell.
Änderungen:
- Fügen Sie ein
timezone-Feld zuEventResponseundEventsListResponsehinzu - Konvertieren Sie Datetimes in API:
datetime.now(timezone.utc)→to_local_timezone() - Passen Sie
row_to_eventan: Konvertieren Sie naive UTC → Benutzer-Zeitzone - Aktualisieren Sie das Template: Verwenden Sie den Zeitzonennamen für Formatierung