Working
Hours &
Holidays

Open-source Kimai plugin for working hours, overtime, vacations, sickness, public holidays and calendar integration — an alternative to the commercial WorkContractBundle.

Open-Source-Kimai-Plugin für Arbeitszeiten, Überstunden, Urlaub, Krankheit, Feiertage und Kalenderanbindung – eine Alternative zum kommerziellen WorkContractBundle.

git clone https://github.com/shrippen/kimai-holiday-bundle.git var/plugins/HolidayBundle && bin/console kimai:reload -n && bin/console kimai:bundle:holiday:install

Remove the commercial WorkContractBundle first. In Docker, run the two bin/console commands as docker exec -it CONTAINER /opt/kimai/bin/console …. To update: git pull in the plugin folder, then run the same two commands.

Entferne zuerst das kommerzielle WorkContractBundle. In Docker führst du die beiden bin/console-Befehle als docker exec -it CONTAINER /opt/kimai/bin/console … aus. Zum Aktualisieren: git pull im Plugin-Ordner, danach dieselben zwei Befehle.

The Absence page of the Working Hours & Holidays pluginThe Absence page of the Working Hours & Holidays plugin
Experimental — This plugin was entirely vibe-coded. Not all functionality is fully tested, especially permissions around the absence approval workflow. Test roles carefully before production use.Experimentell – Dieses Plugin wurde komplett vibe-codiert. Nicht alle Funktionen sind vollständig getestet, besonders die Rechte rund um den Freigabe-Workflow für Abwesenheiten. Teste Rollen sorgfältig, bevor du es produktiv einsetzt.
5Absence typesAbwesenheitsarten
30+Countries with curated holiday calendarsLänder mit kuratierten Feiertagskalendern
1ICS feed per userICS-Feed pro Nutzer
GPL-3Open sourceOpen Source
Working timesArbeitszeiten

Working Times Integration

Integration in die Arbeitszeiten

Absences and public holidays appear directly in Kimai's Arbeitszeiten table — including known future days. Distinctive icons per absence type.

Abwesenheiten und Feiertage erscheinen direkt in der Arbeitszeiten-Tabelle von Kimai – auch bekannte zukünftige Tage. Eigene Symbole pro Abwesenheitsart.

AbsencesAbwesenheiten

Vacation & Absences

Urlaub & Abwesenheiten

Vacation (half-day), sickness (+ relatives), Freizeitausgleich, and custom types. Approval workflow with email notifications, edit-with-reapproval, and bulk approve or reject with undo.

Urlaub (auch halbe Tage), Krankheit (+ Angehörige), Freizeitausgleich und eigene Arten. Freigabe-Workflow mit E-Mail-Benachrichtigung, erneuter Freigabe nach Änderungen und Sammel-Freigabe oder -Ablehnung mit Rückgängig.

HolidaysFeiertage

Public Holidays via ICS

Feiertage per ICS

Import holidays from curated regional calendars (Germany, Austria, Switzerland, 30+ countries) or any custom ICS URL. Auto-sync via cron.

Feiertage aus kuratierten regionalen Kalendern (Deutschland, Österreich, Schweiz, über 30 Länder) oder einer beliebigen ICS-URL importieren. Automatischer Abgleich per Cron.

ICS

Per-User ICS Calendar

ICS-Kalender pro Nutzer

Each user gets a personal calendar subscription URL with public holidays and approved absences — locale-aware, for Outlook, Google, or Apple Calendar.

Jeder Nutzer erhält eine persönliche Kalender-Abo-URL mit Feiertagen und genehmigten Abwesenheiten – sprachabhängig, für Outlook, Google oder Apple Kalender.

ReportsBerichte

Absence Calendar & Reports

Abwesenheitskalender & Berichte

Absence calendar by month or year with team view, CSV export, and per-absence workday count. Weekends and non-working days are automatically excluded.

Abwesenheitskalender nach Monat oder Jahr mit Teamansicht, CSV-Export und Arbeitstage pro Abwesenheit. Wochenenden und arbeitsfreie Tage werden automatisch ausgenommen.

SettingsEinstellungen

Month Locks & Settings

Monatssperren & Einstellungen

Lock months for approval. Configurable calculation modes (compensate vs reduce), comment requirements, and workday timesheet restrictions.

Monate zur Freigabe sperren. Einstellbare Berechnungsmodi (ausgleichen oder reduzieren), Kommentarpflicht und Einschränkungen für Zeiterfassung an Arbeitstagen.

AbsencesAbwesenheiten

Request, track and approve absences

Abwesenheiten beantragen, verfolgen und freigeben

The Absences page is where everyone books time off. Create absence opens a form in a Kimai dialog: pick a type, set start and end, tick half day if needed and save. At the top, tiles show the vacation taken, requested and remaining and the sick days of the year, and a period navigator pages through the years.

Auf der Seite Abwesenheiten bucht jeder seine freie Zeit. Abwesenheit anlegen öffnet ein Formular in einem Kimai-Dialog: Art wählen, Beginn und Ende setzen, bei Bedarf „Halber Tag“ anhaken und speichern. Oben zeigen Kacheln den genommenen, beantragten und verbleibenden Urlaub und die Krankheitstage des Jahres, und ein Zeitraum-Navigator blättert durch die Jahre.

  • Vacation, sickness, sickness of a relative, Freizeitausgleich and other
  • Optional duration in hours for “other” absences, for example 4 for half a day; left empty it uses the contractual day length
  • Only working days count, weekends are left out
  • Approval workflow with email notifications; editing resets the approval when the type requires it
  • Approvers select several absences and approve or reject them at once; for 15 minutes the action can be undone
  • Team leads only see and approve members of their own teams
  • A personal ICS link in the page header, which you can renew at any time
  • Urlaub, Krankheit, Krankheit eines Angehörigen, Freizeitausgleich und Sonstiges
  • Optionale Dauer in Stunden für „Sonstige“ Abwesenheiten, etwa 4 für einen halben Tag; leer nutzt die vertragliche Tageslänge
  • Nur Arbeitstage zählen, Wochenenden bleiben außen vor
  • Freigabe-Workflow mit E-Mail-Benachrichtigung; beim Bearbeiten wird die Freigabe zurückgesetzt, wenn die Art es verlangt
  • Freigebende wählen mehrere Abwesenheiten aus und geben sie auf einmal frei oder lehnen sie ab; 15 Minuten lang lässt sich das rückgängig machen
  • Teamleiter sehen und genehmigen nur Mitglieder ihrer eigenen Teams
  • Ein persönlicher ICS-Link im Seitenkopf, den du jederzeit neu erzeugen kannst
The Absence page with vacation account, personal ICS link, the form for a new absence and the list of absencesThe Absence page with vacation account, personal ICS link, the form for a new absence and the list of absences
The Absence page: vacation account, ICS link and the formDie Seite Abwesenheit: Urlaubskonto, ICS-Link und Formular

Everything in the working times table

Alles in der Arbeitszeiten-Tabelle

Kimai’s own Arbeitszeiten year view gets the absences and public holidays added: one row per month, one column per day, with an icon for each type. Days that are not reached yet are shown too, so planned vacation is visible right away.

Die Jahresansicht Arbeitszeiten von Kimai bekommt die Abwesenheiten und Feiertage dazu: eine Zeile pro Monat, eine Spalte pro Tag, mit einem Symbol je Art. Auch Tage, die noch nicht erreicht sind, werden angezeigt, geplanter Urlaub ist also sofort sichtbar.

Kimai working times year view with months as rows, days as columns and absence iconsKimai working times year view with months as rows, days as columns and absence icons
Working times: months by days, with totals, expected and worked hours, and a lock per monthArbeitszeiten: Monate nach Tagen, mit Gesamt, erwarteten und geleisteten Stunden sowie einem Schloss pro Monat
TeamTeam

One calendar for the whole team

Ein Kalender für das ganze Team

The Absence calendar shows one month or a whole year, with one row per person. Choose a team, switch between month and year, page through the periods and use the legend to read the icons. Requested absences are shown faded, weekends shaded. The data can be exported as CSV.

Der Abwesenheitskalender zeigt einen Monat oder ein ganzes Jahr, mit einer Zeile pro Person. Wähle ein Team, wechsle zwischen Monat und Jahr, blättere durch die Zeiträume und lies die Symbole in der Legende ab. Beantragte Abwesenheiten erscheinen blass, Wochenenden schattiert. Die Daten lassen sich als CSV exportieren.

  • Team picker, month and year view
  • Icons per type: vacation, sickness, sickness of a relative, Freizeitausgleich, other
  • Seeing others needs the permissions view_team_absence or view_other_absence
  • Absences and public holidays also appear in Kimai’s own calendar
  • Teamauswahl, Monats- und Jahresansicht
  • Symbole je Art: Urlaub, Krankheit, Krankheit eines Angehörigen, Freizeitausgleich, Sonstiges
  • Andere zu sehen braucht die Rechte view_team_absence oder view_other_absence
  • Abwesenheiten und Feiertage erscheinen auch im eigenen Kalender von Kimai
The absence calendar with a team selector, a legend and one table per monthThe absence calendar with a team selector, a legend and one table per month
Absence calendar: team, legend and months with one row per personAbwesenheitskalender: Team, Legende und Monate mit einer Zeile pro Person

Public holidays

Feiertage

Public holidays live in groups, and every user’s contract points to one group. Fill a group by hand, or import it from an ICS calendar and keep it in sync.

Feiertage liegen in Gruppen, und der Vertrag jedes Nutzers zeigt auf eine Gruppe. Befülle eine Gruppe von Hand oder importiere sie aus einem ICS-Kalender und halte sie synchron.

ICS sourceCurated calendars, Google holiday calendars or your own URLKuratierte Kalender, Google-Feiertagskalender oder deine eigene URL
ImportInto a holiday group, or manual entryIn eine Feiertagsgruppe, oder manuelle Eingabe
ContractEach user’s contract picks a groupDer Vertrag jedes Nutzers wählt eine Gruppe
Working timesHolidays show up in the year viewFeiertage erscheinen in der Jahresansicht

Install

Installation

  1. Remove the commercial WorkContractBundle first if it is installed.
  2. Clone the plugin into var/plugins/HolidayBundle; the folder name must stay HolidayBundle and contain HolidayBundle.php.
  3. Run bin/console kimai:reload -n and bin/console kimai:bundle:holiday:install. In the official Docker image use the full path /opt/kimai/bin/console with docker exec.
  4. Assign the permissions under System → Roles, in the section Working Hours & Holidays.
  5. Set vacation days, holiday group and contract dates under Profile → Working contract.
  1. Entferne zuerst das kommerzielle WorkContractBundle, falls es installiert ist.
  2. Klone das Plugin nach var/plugins/HolidayBundle; der Ordnername muss HolidayBundle bleiben und HolidayBundle.php enthalten.
  3. Führe bin/console kimai:reload -n und bin/console kimai:bundle:holiday:install aus. Im offiziellen Docker-Image nutzt du mit docker exec den vollen Pfad /opt/kimai/bin/console.
  4. Vergib die Rechte unter System → Rollen, im Abschnitt Working Hours & Holidays.
  5. Trage Urlaubstage, Feiertagsgruppe und Vertragsdaten unter Profil → Arbeitsvertrag ein.

System settings

Systemeinstellungen

Compatibility

Kompatibilität

Permissions

Rechte

PermissionRechtPurposeZweck
hours_own_profile / hours_other_profileWorking times screenArbeitszeiten-Ansicht
contract_other_profileEdit other users' contractsVerträge anderer Nutzer bearbeiten
view_booking_contract / create_booking_contractPDF / manual bookingsPDF / manuelle Buchungen
approve_times_contract / unlock_times_contractMonth lock / unlockMonat sperren / entsperren
absence, edit_*_absence, delete_*_absenceAbsence UIAbwesenheits-Oberfläche
view_team_absence / view_other_absenceTeam / other users in reportsTeam / andere Nutzer in Berichten
approve_*_absence / approval_other_absenceApproval workflowFreigabe-Workflow
edit_public_holidaysAdmin public holidaysFeiertage verwalten (Admin)

REST API

REST-API

GET /api/holiday/absences?year=2026 POST /api/holiday/absences POST /api/holiday/absences/{id}/approve POST /api/holiday/absences/{id}/reject GET /api/holiday/absences/types GET /api/holiday/public-holidays?year=2026 GET /api/holiday/public-holidays/calendar

Questions

Fragen

Can I use it together with the commercial WorkContractBundle?Kann ich es zusammen mit dem kommerziellen WorkContractBundle nutzen?

No. The two cover the same feature area and permissions, so remove the commercial plugin first. Permission names and screens overlap on purpose, so existing documentation and habits carry over.

Nein. Beide decken denselben Funktionsbereich und dieselben Rechte ab, entferne also zuerst das kommerzielle Plugin. Namen der Rechte und Bildschirme überschneiden sich absichtlich, vorhandene Dokumentation und Gewohnheiten bleiben nutzbar.

Is it ready for production?Ist es produktionsreif?

It is experimental and entirely vibe-coded. Not everything is tested end to end, and the permissions around the approval workflow have not been fully verified: own against other users, team lead against admin, approve, reject, edit and delete. Test your roles carefully first.

Es ist experimentell und komplett vibe-codiert. Nicht alles ist Ende zu Ende getestet, und die Rechte rund um den Freigabe-Workflow sind nicht vollständig geprüft: eigene gegen andere Nutzer, Teamleitung gegen Admin, freigeben, ablehnen, bearbeiten und löschen. Teste deine Rollen zuerst sorgfältig.

Which calendars can I subscribe to?Welche Kalender kann ich abonnieren?

Every user has a personal ICS link on the Absence page with public holidays and approved absences, weekends excluded. It works in Outlook, Google Calendar and Apple Calendar, and you can renew the link at any time.

Jeder Nutzer hat auf der Seite Abwesenheit einen persönlichen ICS-Link mit Feiertagen und genehmigten Abwesenheiten, Wochenenden ausgenommen. Er funktioniert in Outlook, Google Kalender und Apple Kalender, und du kannst den Link jederzeit neu erzeugen.

Is there an API?Gibt es eine API?

Yes, a REST API under /api/holiday/… for absences, their approval and public holidays. See the examples above.

Ja, eine REST-API unter /api/holiday/… für Abwesenheiten, deren Freigabe und Feiertage. Beispiele stehen oben.