Desktop-App zur Erfassung von Arbeitszeiten mit Kalenderansicht, PDF-Report und automatischem Gmail-Versand.
- Kalenderansicht — Monatsübersicht mit Tageseinträgen (Start, Ende, Pause)
- PDF-Report — Automatische Generierung als druckfreundliches PDF
- E-Mail-Versand — HTML-E-Mail mit PDF-Anhang über Gmail API (OAuth2)
- Zeitraumwahl — Flexibler Datumsbereich für Reports
- Einstellungen — E-Mail-Vorlagen mit Platzhaltern, Standardpause, Empfänger
- Autostart — Optionaler minimierter Start bei Anmeldung (Windows, macOS, Linux)
- Update-Check — Prüft beim Start einmal pro Tag auf neuere Releases und zeigt einen unaufdringlichen Banner mit Direkt-Download
- Dark Mode UI — Modernes dunkles Design
- Standalone .exe — Per PyInstaller als einzelne Datei paketierbar
Zeiterfassung/
├── src/
│ ├── main.py # Einstiegspunkt
│ ├── ui.py # Tkinter-GUI (Kalender, Dialoge, Einstellungen)
│ ├── storage.py # JSON-basierte Speicherung der Zeiteinträge
│ ├── settings.py # Einstellungen mit Standardwerten
│ ├── report.py # HTML- & PDF-Reportgenerierung
│ ├── mail.py # Gmail OAuth2-Authentifizierung & Versand
│ ├── autostart.py # Plattformabhängiger Autostart (Windows/macOS/Linux)
│ ├── updater.py # GitHub-Releases-Check (stdlib-only, gedrosselt 1×/Tag)
│ ├── time_utils.py # Zeitberechnung und Validierung
│ └── paths.py # Pfadauflösung (Script- vs. Frozen-Modus)
├── tests/ # pytest-Testdateien
├── assets/
│ └── margenheld-icon # App-Icon (.png + .ico + .icns)
├── docs/
│ └── gmail-setup.md # Gmail-Einrichtungsanleitung
├── build.py # PyInstaller-Buildskript
├── Zeiterfassung.spec # PyInstaller-Konfiguration
├── requirements.txt # Python-Abhängigkeiten
├── settings.json # Benutzereinstellungen (wird automatisch erstellt)
└── zeiterfassung.json # Gespeicherte Zeiteinträge (wird automatisch erstellt)
Vorgefertigte Installer für alle drei Plattformen gibt es unter Releases:
Windows
Lade Zeiterfassung_Setup.exe und führe den Installer aus. App installiert nach %LOCALAPPDATA%\Programs\Zeiterfassung\.
macOS (Apple Silicon)
Lade Zeiterfassung-<ver>-arm64.dmg herunter. Öffne das DMG und ziehe die App in den Applications-Ordner. Beim ersten Start: Rechtsklick auf die App → „Öffnen" (Gatekeeper-Warnung bestätigen), oder im Terminal:
xattr -dr com.apple.quarantine /Applications/Zeiterfassung.appDer Build ist nicht signiert — dieser Schritt ist einmalig nötig.
Linux
Lade Zeiterfassung-<ver>-x86_64.AppImage herunter:
chmod +x Zeiterfassung-<ver>-x86_64.AppImage
./Zeiterfassung-<ver>-x86_64.AppImageVoraussetzung: libfuse2 installiert (sudo apt install libfuse2 unter Debian/Ubuntu).
- Python 3.10+
- Windows 10/11, macOS 12+ oder Linux (mit Tkinter)
Tkinter ist unter Linux nicht immer vorinstalliert:
# Debian / Ubuntu
sudo apt install python3-tk
# Fedora
sudo dnf install python3-tkinter
# Arch
sudo pacman -S tk# Repository klonen
git clone <repo-url>
cd Zeiterfassung
# Abhängigkeiten installieren
pip install -r requirements.txt
# App starten
python -m src.main| Paket | Zweck |
|---|---|
google-auth-oauthlib |
OAuth2-Authentifizierung für Gmail |
google-api-python-client |
Gmail API Client |
xhtml2pdf |
PDF-Generierung aus HTML |
pyinstaller |
Paketierung als Standalone-Binary |
Damit die App E-Mails versenden kann, muss einmalig ein Google Cloud Projekt mit Gmail API eingerichtet werden.
- Google Cloud Console öffnen
- Projekt-Dropdown → Neues Projekt → Name: "Zeiterfassung" → Erstellen
- APIs & Dienste → Bibliothek
- Nach "Gmail API" suchen → Aktivieren
- APIs & Dienste → OAuth-Zustimmungsbildschirm
- Extern → Erstellen
- Ausfüllen:
- App-Name: "Zeiterfassung"
- Support-E-Mail: deine Gmail-Adresse
- Entwickler-E-Mail: deine Gmail-Adresse
- Speichern und fortfahren
- Bei Bereiche:
gmail.sendhinzufügen → Aktualisieren → Speichern - Bei Testnutzer: deine Gmail-Adresse hinzufügen → Speichern
- APIs & Dienste → Anmeldedaten
- Anmeldedaten erstellen → OAuth-Client-ID
- Anwendungstyp: Desktopanwendung → Name: "Zeiterfassung" → Erstellen
- JSON herunterladen → als
credentials.jsonspeichern:- Entwicklung (aus dem Source): im Projekt-Root
- Windows (installiert):
%LOCALAPPDATA%\Programs\Zeiterfassung\ - macOS (installiert):
~/Library/Application Support/Zeiterfassung/ - Linux (AppImage):
~/.local/share/Zeiterfassung/(oder$XDG_DATA_HOME/Zeiterfassung/)
- App starten
- Unter Einstellungen (⚙) E-Mail und Empfänger eintragen
- Monat senden klicken
- Browser öffnet sich → mit Google anmelden → Zugriff erlauben
token.jsonwird automatisch erstellt — ab jetzt kein erneutes Anmelden nötig
- Die App läuft im Test-Modus — nur eingetragene Testnutzer können sich authentifizieren
- Das Token wird automatisch erneuert; bei Ablauf öffnet sich der Browser erneut
credentials.jsonundtoken.jsongehören nicht ins Repository
Über das Zahnrad-Symbol (⚙) im Header konfigurierbar:
| Einstellung | Beschreibung |
|---|---|
| Eigene Gmail-Adresse (Absender) | |
| Empfänger | E-Mail-Adresse für den Report |
| Name | Vollständiger Name (erscheint im PDF) |
| Standard-Pause | Standardmäßige Pausendauer in Minuten |
| Betreff | E-Mail-Betreff mit Platzhaltern |
| Begrüßung | Anrede im E-Mail-Text |
| Inhalt | E-Mail-Body mit Platzhaltern |
| Grußformel | Abschluss der E-Mail (Zeilenumbrüche mit \n) |
| Autostart | App minimiert bei Systemanmeldung starten (Windows/macOS/Linux) |
| Platzhalter | Wird ersetzt durch |
|---|---|
{zeitraum} |
Datumsbereich, z.B. "01.03.2026 – 31.03.2026" |
{gesamt} |
Gesamtstunden, z.B. "168.5h" |
python build.pybuild.py erkennt die Plattform via platform.system() und baut das passende Artefakt:
| Plattform | Voraussetzung | Ausgabe |
|---|---|---|
| Windows | Inno Setup 6 unter %LOCALAPPDATA%\Programs\Inno Setup 6\ |
dist/Zeiterfassung_Setup.exe |
| macOS | brew install create-dmg |
dist/Zeiterfassung-<ver>-<arch>.dmg |
| Linux | apt install libfuse2 + appimagetool auf $PATH |
dist/Zeiterfassung-<ver>-<arch>.AppImage |
Fehlt das Pack-Tool, überspringt build.py den Pack-Schritt mit Warnung — der PyInstaller-Build läuft trotzdem durch.
Die App läuft auf Windows, macOS und Linux. Plattformspezifische Features werden automatisch erkannt:
| Feature | Windows | macOS | Linux |
|---|---|---|---|
| Kalender & Zeiterfassung | ✓ | ✓ | ✓ |
| PDF-Report & E-Mail-Versand | ✓ | ✓ | ✓ |
| Einstellungen & Vorlagen | ✓ | ✓ | ✓ |
| Taskbar-Icon (AppUserModelID) | ✓ | — (nicht nötig) | — (nicht nötig) |
| Window-Icon | ✓ (.ico) |
✓ (.png Fallback) |
✓ (.png Fallback) |
| Autostart bei Anmeldung | ✓ (VBScript-Shortcut) | ✓ (LaunchAgent plist) | ✓ (.desktop-Datei) |
| Standalone-Binary (PyInstaller) | ✓ (.exe) |
✓ (.app Bundle) |
✓ (AppImage) |
pytest tests/Alle Daten werden lokal als JSON gespeichert:
- zeiterfassung.json — Zeiteinträge (Schlüssel: ISO-Datum
YYYY-MM-DD) - settings.json — Benutzereinstellungen
- token.json — Gmail OAuth-Token (wird automatisch erneuert)
Speicherort je nach Plattform (siehe src/paths.py):
| Plattform | Pfad |
|---|---|
| Windows (installiert) | %LOCALAPPDATA%\Programs\Zeiterfassung\ |
| macOS (installiert) | ~/Library/Application Support/Zeiterfassung/ |
| Linux (AppImage) | $XDG_DATA_HOME/Zeiterfassung/ (Fallback ~/.local/share/Zeiterfassung/) |
| Entwicklung (Source) | Projekt-Root |