Functional Weave
Code in Python

payroll.notice-period

Statutory minimum notice in weeks from continuous service: one week per year from two years, capped at twelve.

1.0.0 (not the latest) · published 2026-10-03 by charlie · Anterra

Pinned by 10 tests, run in TypeScript, Python and Rust.

Not professional advice. This capability calculates payroll figures from published rules. It is a software component for developers, not tax or legal advice. Rules change and every rate here has an effective date. Check that the dates cover your case. Verify results against the official sources listed in its README, and have a payroll specialist review how you use it, before anyone relies on the output. Provided “as is” under its licence, without warranty.

What it does

The statutory minimum notice for ending a contract of employment in Great Britain, from the Employment Rights Act 1996 s.86:

| Continuous service on the day notice is given | Employer must give | Employee must give | |---|---|---| | under one month | no statutory minimum (0) | no statutory minimum (0) | | one month to under two years | 1 week | 1 week | | two years to under twelve years | 1 week per completed year | 1 week | | twelve years or more | 12 weeks | 1 week |

For example

  • statutory_notice(2026-09-01, 2026-09-23) → service years 0, employer weeks 0, employee weeks 0 under a month's service: no statutory notice either way
  • statutory_notice(2026-08-25, 2026-09-23) → service years 0, employer weeks 0, employee weeks 0 one day short of a month
  • statutory_notice(2026-08-24, 2026-09-23) → service years 0, employer weeks 1, employee weeks 1 exactly one month: one week each way

The function

The same function in TypeScript, Python and Rust, pinned by the same tests. Pick your language; the choice follows you around the registry.

def statutory_notice(start_date: str, notice_date: str) -> StatutoryNotice
start_datedatefirst day of continuous employment
notice_datedatethe day notice is given; service is counted up to and including it
returnsStatutoryNotice

The type it declares, generated into your project

@dataclass(frozen=True)
class StatutoryNotice:
    """The minimum each side must give under ERA 1996 s.86."""

    #: completed years of continuous service on noticeDate
    service_years: int
    #: minimum notice the employer must give: 0 under one month's service
    employer_weeks: int
    #: minimum notice the employee must give: 1 week from one month's service, never more
    employee_weeks: int

Your code names it in one line, in the file that uses it

from fune.payroll.notice_period import statutory_notice  # payroll.notice-period@^1
impl/python.py · 19 lines · open · raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

from .hr_length_of_service import length_of_service  ← from hr.length-of-service ^1.0.0 · built alongside by fune
from .payroll_notice_period_types import StatutoryNotice


def statutory_notice(start_date: str, notice_date: str) -> StatutoryNotice:
    """ERA 1996 s.86 minimum notice. Below one month's service the section does
    not apply at all, which is different from one week: an employer who
    dismisses on day 20 owes no statutory notice.
    """
    service = length_of_service(start_date, notice_date)
    at_least_one_month = service.years > 0 or service.months > 0
    employer_weeks = 0
    if at_least_one_month:
        employer_weeks = 1 if service.years < 2 else min(service.years, 12)
    return StatutoryNotice(
        service_years=service.years,
        employer_weeks=employer_weeks,
        employee_weeks=1 if at_least_one_month else 0,
    )

Install

fune build

With that line in your source, in a Python project (language python in fune.project), fune build resolves it and its 1 dependency, pins them in fune.lock, downloads only the Python package of each, and builds the code above into your project’s .fune/build, one readable file per capability with a header linking back here. Or pin a range in fune.project and build in one step:

fune add payroll.notice-period
Download for Python payroll.notice-period-1.0.0-python.fune · 6,021 bytes sha256 53330857bd75fabd8cd94167e0af074c849ddf42719b0f108e0b99791f4542df

The manifest, vectors and README with only the Python implementation. Install it without the registry with fune add ./payroll.notice-period-1.0.0-python.fune, or fetch it from a terminal with fune pull payroll.notice-period@1.0.0:python.

The whole function, every language, is one file too: payroll.notice-period-1.0.0.fune, 8,084 bytes, sha256 2ffa1493b724e7a2ad4e78005fe7800be20ff73a78fe669ee042abed9ce74163. It installs into a project of any language.

Customise it in your app

The seams this capability offers. Put a marker directly above a function of your own and fune build wires it into the built code; the package on the registry is not changed, the built file’s header lists it under CUSTOMISED, and fune hooks lists every hook in the project. How hooks work.

before — your function gets the arguments and returns them, changed or not, or throws to refuse the call.

# fune: before payroll.notice-period

after — your function gets the result and the arguments, and returns the final result.

# fune: after payroll.notice-period

replace — inside this capability’s code only, calls to a dependency go to your function, with the same signature. Other capabilities that use it are unaffected; write in * to replace it everywhere.

# fune: replace hr.length-of-service in payroll.notice-period

step — your function runs at a numbered point inside the function’s body, receives the in-scope values it names as parameters, and may return replacements. List the points with fune show payroll.notice-period --steps.

# fune: step payroll.notice-period after <n|label>

Tests

A version published now needs at least 8 tests for every function, and one that expects the error for each function that throws; the registry refuses it otherwise. fune verify --all runs each case in TypeScript, Python and Rust, and a project runs them again with fune verify. This page lists the cases; it does not run them. The exact JSON is vectors.json.

CaseArgumentsExpected
under a month's service: no statutory notice either way 2026-09-01, 2026-09-23 → service years 0, employer weeks 0, employee weeks 0
one day short of a month 2026-08-25, 2026-09-23 → service years 0, employer weeks 0, employee weeks 0
exactly one month: one week each way 2026-08-24, 2026-09-23 → service years 0, employer weeks 1, employee weeks 1
a day short of two years is still one week 2024-01-01, 2025-12-30 → service years 1, employer weeks 1, employee weeks 1
two years on the anniversary: two weeks 2024-01-01, 2025-12-31 → service years 2, employer weeks 2, employee weeks 1
six completed years: six weeks 2020-03-15, 2026-09-23 → service years 6, employer weeks 6, employee weeks 1
a day short of twelve years is eleven weeks 2014-04-01, 2026-03-30 → service years 11, employer weeks 11, employee weeks 1
twelve years: twelve weeks 2014-04-01, 2026-03-31 → service years 12, employer weeks 12, employee weeks 1
thirty years is capped at twelve weeks 1996-01-01, 2026-01-01 → service years 30, employer weeks 12, employee weeks 1
notice before the start date is an error 2026-09-23, 2026-09-01 → error: is before startDate

More from the author

Service is measured with hr.length-of-service up to and including the day notice is given, so the extra week arrives on the anniversary itself.

A contract can give longer notice, never shorter; this returns only the statutory floor. It does not cover summary dismissal for gross misconduct, payment in lieu, or s.86(4) (fixed-term contracts of a month or less treated as indefinite after three months' service). Northern Ireland has its own equivalent legislation and is not covered.

Source: Employment Rights Act 1996 s.86, "Rights of employer and employee to minimum notice", https://www.legislation.gov.uk/ukpga/1996/18/section/86.

Files

PathBytes
README.md1,138
impl/python.py810
impl/rust.rs1,204
impl/typescript.ts770
vectors.json1,637