Workdays & Public Holidays Calculator (Poland, Germany)
Pricing
$10.00 / 1,000 completed date ranges
Workdays & Public Holidays Calculator (Poland, Germany)
Calculate working days, public holidays and crew hours for Poland and all 16 German states. Compare date ranges in batches, add custom days off and export a day-by-day calendar. Offline calculations; no external API or credentials needed.
Pricing
$10.00 / 1,000 completed date ranges
Rating
0.0
(0)
Developer
Daniel Michałek
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Count working days, public holidays and crew hours for date ranges of up to 3660 days in Poland or Germany (nationwide or for any of the 16 German states). Built for payroll and timesheet checks, project and crew planning, invoicing of day rates, and SLA / delivery-date calculations.
What it does
For each requested date range the Actor returns:
- the number of calendar days, weekend days, public holidays and workdays,
- the list of public holidays in the range (English and local names, national or state scope),
- hours per worker and crew hours (
billable workdays x hoursPerDay x crewSize), - optionally a day-by-day calendar.
Holidays are computed from the statutory rules, with movable feasts derived from the Gregorian Easter date:
- Poland - all nationwide statutory days off (ustawa o dniach wolnych od pracy), including Epiphany (since 2011), the one-off holiday on 12 November 2018, and Christmas Eve (since 2025). Optionally applies the Labour Code rule that a holiday falling on a Saturday grants another day off (Kodeks pracy art. 130 § 2).
- Germany - nationwide holidays, plus the statewide holidays of the selected state (
BW,BY,BE,BB,HB,HH,HE,MV,NI,NW,RP,SL,SN,ST,SH,TH), including one-off days such as Reformation Day 2017, Berlin's Liberation Day 2020/2025, and Berlin's 1953 uprising anniversary on 17 June 2028.
Input
| Field | Type | Default | Description |
|---|---|---|---|
country | PL or DE | PL | Country whose public holidays apply. |
region | German state code | - | DE only. Adds statewide holidays (inside ranges the DE-BY form is accepted too). Must be empty for PL. |
startDate | YYYY-MM-DD | - | First day of the range (years 2000-2100). |
endDate | YYYY-MM-DD | startDate | Last day of the range, inclusive (max 3660 days). |
workingWeekdays | array of 1-7 | [1,2,3,4,5] | ISO weekdays normally worked (1 = Monday, 7 = Sunday). |
hoursPerDay | string number | "8" | Hours per working day per person, > 0 and <= 24, e.g. "7.5". |
crewSize | integer | 1 | Number of people (1-100000). |
extraDaysOff | array of dates | - | Additional non-working days (company holidays, bridge days, the designated day for a Polish Saturday holiday). |
compensateSaturdayHolidays | boolean | false | PL only: subtract one billable day for each holiday falling on a non-working Saturday. |
includeDays | boolean | false | Add a days array with one entry per calendar day. |
ranges | array | - | Batch mode: several ranges in one run. Each item may override any field above (except includeDays) and may carry an id. |
Example - Polish working time for 2026:
{"country": "PL","startDate": "2026-01-01","endDate": "2026-12-31","hoursPerDay": "8","crewSize": 12}
Example - batch, one record per month and one for Bavaria:
{"country": "PL","ranges": [{ "id": "PL-2026-01", "startDate": "2026-01-01", "endDate": "2026-01-31" },{ "id": "PL-2026-02", "startDate": "2026-02-01", "endDate": "2026-02-28" },{ "id": "BY-2026", "country": "DE", "region": "BY", "startDate": "2026-01-01", "endDate": "2026-12-31" }]}
Output
One dataset item per range (shortened; Poland 2026 with default hoursPerDay and crewSize):
{"id": null,"rangeIndex": 0,"status": "ok","country": "PL","region": null,"regionName": null,"startDate": "2026-01-01","endDate": "2026-12-31","summary": {"calendarDays": 365,"weekendDays": 104,"holidays": 14,"holidaysOnWorkingDays": 8,"extraDaysOffApplied": 0,"workdays": 253,"saturdayHolidays": ["2026-08-15", "2026-12-26"],"compensateSaturdayHolidays": false,"billableWorkdays": 253,"hoursPerDay": 8,"crewSize": 1,"hoursPerWorker": 2024,"crewHours": 2024},"holidays": [{ "date": "2026-01-01", "name": "New Year's Day", "localName": "Nowy Rok", "country": "PL", "scope": "national" }],"notes": ["Polish holidays falling on Saturday entitle employees to another day off (KP art. 130 § 2); ..."]}
With includeDays: true each item also contains days:
{ "date", "weekday", "weekdayName", "isWorkday", "isWeekend", "holiday", "holidayLocal", "extraDayOff" }.
A range with invalid input (e.g. an impossible date, a region for Poland) is returned with
status: "error", error (code) and message. If no range can be computed, the run fails.
A run summary is stored in the default key-value store under OUTPUT.
Pricing (pay per event)
| Event | Charged when |
|---|---|
date-range-computed | once per range with status: "ok" |
Ranges with status: "error" are returned but never charged. The price per event is shown on the
Actor's Pricing tab in Apify Store. If your maximum charge per run is reached, the Actor
stops after the last paid range and sets stoppedByChargeLimit: true in OUTPUT.
An explicit zero maximum charge prevents new paid results and charges, including when the SDK interprets zero as an unlimited budget.
Limitations
- No scraping, no external API. Everything is computed offline from statutory rules; results do not depend on any website being available.
- Germany: holidays that apply only in some municipalities are not included - e.g.
Assumption Day in parts of Bavaria, Corpus Christi in parts of Saxony and Thuringia, and the
Augsburger Friedensfest. Without
region, only nationwide German holidays are applied. - Poland: there are no regional public holidays; Saturday-holiday compensation is a simple
one-day reduction per holiday - the actual designated day off is set by each employer (list it in
extraDaysOffif you know it). Do not combine explicit extra days off with automatic Saturday compensation. - Years 2000-2100 only; future statutory changes after the release of this version are not reflected until the Actor is updated.
- Church or company-specific days off, school holidays and shortened working days are not
modelled unless you add them via
extraDaysOff. - This is a calculation aid, not legal or payroll advice.
Safe batch limits and recovery
Combined valid ranges are limited to 100,000 calendar days and the input to 1 MB per run. Each full result is durably saved in a DELIVERY- record before its custom charge. A restart reconciles existing results and does not blindly charge them again. An ambiguous charge stops for review. The SDK event count is a billing receipt, not proof of creator revenue. Free development runs report zero custom charges.
For a quick synthetic test, January 2026 in Poland with four people and eight hours per day returns 20 working days and 640 crew hours. Calendar rules are an offline snapshot; verify future statutory changes before payroll use.
Legal source for the historical one-off holiday: https://eli.gov.pl/eli/DU/2018/2117/ogl . Christmas Eve amendment: https://eli.gov.pl/eli/DU/2024/1965/ogl . Berlin's one-off 17 June 2028 holiday: fourth amendment of 10 July 2024, Article 1, GVBl. 2024 p. 460: https://www.berlin.de/sen/justiz/service/gesetze-und-verordnungen/2024/ausgabe-nr-28-vom-2072024-s-457-484.pdf .
Release packaging
The deployment Dockerfile installs locked dependencies with TLS verification enabled and prints source-file SHA256 values in the build log so the uploaded files can be compared with the reviewed package. It does not require BuildKit secret mounts. A separate local proxy-CA Dockerfile is retained only in verification evidence; that variant passed the local container build and smoke. The production Dockerfile's native Apify build and hosted verification are pending. This packaging adjustment does not change the application code.