How the Ireland annual leave calculator is verified

Inputs

InputFieldType
Days you usually work per weekdaysPerWeeknumber
Hours you usually work per weekhoursPerWeeknumber
Months worked in the leave year (0–12)monthsWorkednumber
I changed employment during this leave yearchangedEmploymentboolean
Days already takendaysTakennumber

The formula

Each derived value below is computed by the Valem engine from the expression shown, in this order. Nothing else runs — there is no hidden code path.

Derived valueFieldFormula (JSONata)
Hours Per DayhoursPerDay($d := $n(daysPerWeek); $d > 0 ? $n(hoursPerWeek) / $d : 0)
Hours Per MonthhoursPerMonth$n(hoursPerWeek) * $const.weeksPerYear / $const.monthsPerYear
Hours WorkedhoursWorkedhoursPerMonth * $n(monthsWorked)
Full Working Weeks DaysfullWorkingWeeksDays$const.workingWeeks * $n(daysPerWeek)
Method ADaysmethodADays(changedEmployment = true or hoursWorked < $const.annualHoursThreshold ? 0 : fullWorkingWeeksDays)
Qualifying MonthsqualifyingMonths(hoursPerMonth >= $const.monthlyHoursThreshold ? $floor($n(monthsWorked)) : 0)
Method BDaysmethodBDaysqualifyingMonths * $n(daysPerWeek) / $const.monthWeekDivisor
Method CHoursmethodCHourshoursWorked * $const.hoursPercentage
Method CDaysmethodCDays(hoursPerDay > 0 ? $clampFloorCap(methodCHours / hoursPerDay, null, fullWorkingWeeksDays) : 0)
Days EntitleddaysEntitled($a := $n(methodADays); $b := $n(methodBDays); $c := $n(methodCDays); $ab := $a > $b ? $a : $b; $g := $ab > $c ? $ab : $c; $round($clampFloorCap($g, null, fullWorkingWeeksDays), 1))
Days RemainingdaysRemaining($r := daysEntitled - $n(daysTaken); $r < 0 ? 0 : $round($r, 1))
Method UsedmethodUsed($m := daysEntitled; $a := $round($n(methodADays), 1) = $m; $b := $round($n(methodBDays), 1) = $m; $c := $round($n(methodCDays), 1) = $m; $m <= 0 ? 'none yet — no qualifying hours in this leave year' : ($a and $b and $c ? 'all three methods give the same answer' : ($a and $b ? 'methods (a) and (b)' : ($a and $c ? 'methods (a) and (c)' : ($b and $c ? 'methods (b) and (c)' : ($a ? 'method (a) — you passed the 1,365-hour threshold' : ($b ? 'method (b) — one-third of a working week per qualifying month' : 'method (c) — 8% of the hours you worked')))))))

Rates and thresholds

The expressions above read these as $const. They are the figures the annual refresh replaces, so they live as data rather than being written into the formulas — which is what makes a year-on-year change a one-line diff instead of an edit to arithmetic.

ConstantValue
workingWeeks4
annualHoursThreshold1365
monthlyHoursThreshold117
monthWeekDivisor3
hoursPercentage0.08
weeksPerYear52
monthsPerYear12

Test vectors (10)

Every case is executed against this model on each build, by the Java engine and independently by a JavaScript one. A mismatch of a single cent fails the build, so the page cannot ship advertising a figure the model no longer produces.

Case 1 — D1 a full-year five-day week is 20 days, and all three methods agree on it

given daysPerWeek5
given hoursPerWeek39
given monthsWorked12
given changedEmploymentno
given daysTaken0
expect methodADays20
expect methodBDays20
expect methodCDays20
expect daysEntitled20
expect methodUsedall three methods give the same answer

Case 2 — D2 a three-day part-timer fails both hour tests, so only method (c) carries them

given daysPerWeek3
given hoursPerWeek24
given monthsWorked12
given changedEmploymentno
given daysTaken0
expect methodADays0
expect methodBDays0
expect methodCDays12
expect daysEntitled12
expect methodUsedmethod (c) — 8% of the hours you worked

Case 3 — D3 half a leave year: method (c)'s 10.4 beats method (b)'s 10, which is what the proviso is for

given daysPerWeek5
given hoursPerWeek39
given monthsWorked6
given changedEmploymentno
given daysTaken0
expect hoursWorked1014
expect methodADays0
expect methodBDays10
expect methodCDays10.4
expect daysEntitled10.4

Case 4 — D4 eleven months on a six-day week clears 1,365 hours, so method (a) pays the full 4 weeks

given daysPerWeek6
given hoursPerWeek45
given monthsWorked11
given changedEmploymentno
given daysTaken0
expect methodADays24
expect methodBDays22
expect daysEntitled24
expect methodUsedmethod (a) — you passed the 1,365-hour threshold

Case 5 — D5 the same year, but employment changed: s.19(1)(a) is unavailable and (c) wins at 22.9

given daysPerWeek6
given hoursPerWeek45
given monthsWorked11
given changedEmploymentyes
given daysTaken0
expect methodADays0
expect daysEntitled22.9
expect methodUsedmethod (c) — 8% of the hours you worked

Case 6 — D6 the four-working-week ceiling holds against a 100-hour week

given daysPerWeek5
given hoursPerWeek100
given monthsWorked12
given changedEmploymentno
given daysTaken0
expect fullWorkingWeeksDays20
expect methodCDays20
expect daysEntitled20

Case 7 — D7 no months worked is no entitlement, and the method label says so rather than naming one

given daysPerWeek5
given hoursPerWeek39
given monthsWorked0
given changedEmploymentno
given daysTaken0
expect daysEntitled0
expect methodUsednone yet — no qualifying hours in this leave year

Case 8 — D8 a two-day week is 8 days, the (c) cap biting on 8.32

given daysPerWeek2
given hoursPerWeek16
given monthsWorked12
given changedEmploymentno
given daysTaken0
expect methodCDays8
expect daysEntitled8

Case 9 — D9 days already taken come off the remainder and it never goes negative

given daysPerWeek5
given hoursPerWeek39
given monthsWorked12
given changedEmploymentno
given daysTaken25
expect daysEntitled20
expect daysRemaining0

Case 10 — D10 days taken below the entitlement leave the balance

given daysPerWeek5
given hoursPerWeek39
given monthsWorked12
given changedEmploymentno
given daysTaken8
expect daysEntitled20
expect daysRemaining12

Sources

Check it yourself — and reuse it

The whole model as JSON — inputs, outputs, formulas, vectors and sources in one re-runnable document.

This model is published under CC BY 4.0: use it, adapt it, build on it, with attribution. The licence covers the model — the expression of each rule and the arrangement of the catalog. The rates and thresholds are law, and nobody licenses those; the sources above are where they come from.

← Back to the Ireland annual leave calculator

Built with Valem — a live, verifiable calculator you can fork and embed.