Functional Weave
Code in TypeScript

legal.limitation-date Unreviewed

The last day to bring a claim under the Limitation Act 1980, by claim type, from the date it accrued.

1.0.1 · published 2026-10-03 by charlie · Anterra

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

Unreviewed. This capability’s implementations agree in every language and pass its published test vectors, which were worked out from the official sources cited. But no qualified litigation solicitor has yet checked those vectors, or confirmed that the capability covers the cases it claims. Treat it as a draft. Do not use it for real people, money or decisions without your own expert review. Once a qualified reviewer signs off, this notice is replaced with their name, qualification and the date. Each new version needs fresh sign-off.

Not professional advice. This capability calculates legal figures from published rules. It is a software component for developers, not 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 litigation solicitor review how you use it, before anyone relies on the output. Provided “as is” under its licence, without warranty.

What it does

Status: needs review by a solicitor before it is published; it does not handle disability, fraud, concealment or date-of-knowledge disputes.

The last day on which a claim may be brought in England and Wales under the Limitation Act 1980, from the claim type and the date the cause of action accrued. The periods are data, one row per claim type, with the section that sets each:

For example

  • limitationDate(contract, 2020-03-15, —) → claim type contract, years 6, section s.5, runs from 2020-03-15, expiry 2026-03-15 a contract breached on 15 March 2020 may be sued on until 15 March 2026
  • limitationDate(tort, 2020-03-15, —) → claim type tort, years 6, section s.2, runs from 2020-03-15, expiry 2026-03-15 the anniversary, not 6 x 365 days (which lands on 14 March 2026)
  • limitationDate(contract, 2020-02-29, —) → claim type contract, years 6, section s.5, runs from 2020-02-29, expiry 2026-02-28 accrued on 29 February: no corresponding date in 2026, so the end of February

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.

export function limitationDate(claimType: string, accrualDate: string, knowledgeDate: string | null): LimitationPeriod
claimTypestringcontract, tort, personal-injury, fatal-accident, defamation, malicious-falsehood, deed, statute-sum, contribution, recovery-of-land, rent-arrears, mortgage-principal, mortgage-interest, judgment or judgment-interest
accrualDatedatethe date the cause of action accrued (for fatal-accident the date of death; for judgment the date it became enforceable)
knowledgeDatedate?personal-injury and fatal-accident only: the claimant's date of knowledge (s.14), or null; must be null for other types
returnsLimitationPeriod

The type it declares, generated into your project

/** The period that applies and the last day it allows. */
export interface LimitationPeriod {
  readonly claimType: string;
  readonly years: number;
  /** the section of the Limitation Act 1980 that sets it */
  readonly section: string;
  /** the accrual date, or the later date of knowledge where the section allows it */
  readonly runsFrom: string;
  /** the last day on which the claim may be brought */
  readonly expiry: string;
}

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

import { limitationDate } from "#fune/legal.limitation-date@^1";
impl/typescript.ts · 39 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.

import { parseIsoDate } from "./dates_add_days.ts";  ← from dates.add-days ^1.0.0 · built alongside by fune
import { addMonths } from "./dates_add_months.ts";  ← from dates.add-months ^1.0.0 · built alongside by fune
import { LIMITATION_PERIODS, LIMITATION_PERIODS_HISTORY } from "./legal_limitation_date_data.ts";  ← this capability’s own data, compiled from data/limitation-periods.json into the same file by fune build
import { type LimitationPeriod } from "./legal_limitation_date_types.ts";

/**
 * The last day to bring a claim: the anniversary of the accrual date (or the
 * later date of knowledge) the period's number of years on, the accrual day
 * itself excluded, and the month's last day where no anniversary exists.
 */
export function limitationDate(claimType: string, accrualDate: string, knowledgeDate: string | null): LimitationPeriod {
  parseIsoDate(accrualDate);
  const rows = LIMITATION_PERIODS.filter((r) => r.claimType === claimType);
  if (rows.length === 0) {
    const known = Array.from(new Set(LIMITATION_PERIODS.map((r) => r.claimType))).join(", ");
    throw new RangeError(`unknown claim type "${claimType}": expected one of ${known}`);
  }
  const rule = rows.find((r) => accrualDate >= r.validFrom && (r.validTo === null || accrualDate <= r.validTo));
  if (rule === undefined) {
    const earliest = rows.map((r) => r.validFrom).reduce((a, b) => (b < a ? b : a));
    if (LIMITATION_PERIODS_HISTORY !== "full" && accrualDate < earliest) {
      throw new RangeError(
        `no limitation rule for ${claimType} accruing on ${accrualDate}: this build was installed with history=${LIMITATION_PERIODS_HISTORY}, so it only carries rules from ${earliest}. Reinstall with history=full for older claims.`,
      );
    }
    throw new RangeError(`no limitation rule for ${claimType} accruing on ${accrualDate}`);
  }
  let runsFrom = accrualDate;
  if (knowledgeDate !== null) {
    if (!rule.fromKnowledge) {
      throw new RangeError(`a ${claimType} claim runs from accrual under ${rule.section}; knowledgeDate must be null`);
    }
    parseIsoDate(knowledgeDate);
    if (knowledgeDate > accrualDate) runsFrom = knowledgeDate;
  }
  // The corresponding date rule: the anniversary, clamped to the month end.
  const expiry = addMonths(runsFrom, rule.years * 12);
  return { claimType, years: rule.years, section: rule.section, runsFrom, expiry };
}

Install

fune build

With that line in your source, in a TypeScript project (language typescript in fune.project), fune build resolves it and its 2 dependencies, pins them in fune.lock, downloads only the TypeScript 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 legal.limitation-date
Download for TypeScript legal.limitation-date-1.0.1-typescript.fune · 24,225 bytes sha256 5009d44ca80668beffbbaaeaf06f426e1061ec365af7623720f73ca96bbcf925

The manifest, vectors and README with only the TypeScript implementation. Install it without the registry with fune add ./legal.limitation-date-1.0.1-typescript.fune, or fetch it from a terminal with fune pull legal.limitation-date@1.0.1:typescript.

The whole function, every language, is one file too: legal.limitation-date-1.0.1.fune, 29,851 bytes, sha256 e158c7c9b69f962c622dbfc6b5caa8b6ab3589271299976d4c6e4fe6c9c8f195. 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 legal.limitation-date

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

// fune: after legal.limitation-date

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 dates.add-days in legal.limitation-date
// fune: replace dates.add-months in legal.limitation-date

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 legal.limitation-date --steps.

// fune: step legal.limitation-date 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
a contract breached on 15 March 2020 may be sued on until 15 March 2026 contract, 2020-03-15, — → claim type contract, years 6, section s.5, runs from 2020-03-15, expiry 2026-03-15
the anniversary, not 6 x 365 days (which lands on 14 March 2026) tort, 2020-03-15, — → claim type tort, years 6, section s.2, runs from 2020-03-15, expiry 2026-03-15
accrued on 29 February: no corresponding date in 2026, so the end of February contract, 2020-02-29, — → claim type contract, years 6, section s.5, runs from 2020-02-29, expiry 2026-02-28
accrued on 28 February: the anniversary, not 29 February in a leap year tort, 2019-02-28, — → claim type tort, years 6, section s.2, runs from 2019-02-28, expiry 2025-02-28
accrued on 31 December: expires 31 December, not 30th or 1 January deed, 2014-12-31, — → claim type deed, years 12, section s.8(1), runs from 2014-12-31, expiry 2026-12-31
personal injury with no later knowledge: 3 years from the accident personal-injury, 2023-06-01, — → claim type personal-injury, years 3, section s.11(4), runs from 2023-06-01, expiry 2026-06-01
personal injury: a later date of knowledge starts the clock personal-injury, 2015-01-10, 2024-11-30 → claim type personal-injury, years 3, section s.11(4), runs from 2024-11-30, expiry 2027-11-30
personal injury: a knowledge date before accrual changes nothing personal-injury, 2023-06-01, 2023-05-01 → claim type personal-injury, years 3, section s.11(4), runs from 2023-06-01, expiry 2026-06-01
fatal accident: 3 years from the date of death fatal-accident, 2024-02-29, — → claim type fatal-accident, years 3, section s.12(2), runs from 2024-02-29, expiry 2027-02-28
defamation: one year from publication defamation, 2025-10-01, — → claim type defamation, years 1, section s.4A, runs from 2025-10-01, expiry 2026-10-01
Show the other 16 tests
CaseArgumentsExpected
defamation accruing on the day the 1996 Act's one-year period began defamation, 1996-09-04, — → claim type defamation, years 1, section s.4A, runs from 1996-09-04, expiry 1997-09-04
malicious falsehood: one year malicious-falsehood, 2026-01-31, — → claim type malicious-falsehood, years 1, section s.4A, runs from 2026-01-31, expiry 2027-01-31
contribution: two years from the judgment contribution, 2025-07-14, — → claim type contribution, years 2, section s.10(1), runs from 2025-07-14, expiry 2027-07-14
recovery of land: twelve years recovery-of-land, 2010-04-06, — → claim type recovery-of-land, years 12, section s.15(1), runs from 2010-04-06, expiry 2022-04-06
rent arrears: six years from the day each instalment fell due rent-arrears, 2021-03-25, — → claim type rent-arrears, years 6, section s.19, runs from 2021-03-25, expiry 2027-03-25
mortgage principal: twelve years mortgage-principal, 2016-08-31, — → claim type mortgage-principal, years 12, section s.20(1), runs from 2016-08-31, expiry 2028-08-31
mortgage interest arrears: six years mortgage-interest, 2016-08-31, — → claim type mortgage-interest, years 6, section s.20(5), runs from 2016-08-31, expiry 2022-08-31
an action on a judgment: six years from when it became enforceable judgment, 2020-01-15, — → claim type judgment, years 6, section s.24(1), runs from 2020-01-15, expiry 2026-01-15
judgment interest arrears: six years judgment-interest, 2020-01-15, — → claim type judgment-interest, years 6, section s.24(2), runs from 2020-01-15, expiry 2026-01-15
sums recoverable by statute: six years statute-sum, 1981-05-01, — → claim type statute-sum, years 6, section s.9(1), runs from 1981-05-01, expiry 1987-05-01
an unknown claim type is an error negligence, 2020-01-01, — → error: unknown claim type "negligence"
a knowledge date for a contract claim is an error, not ignored contract, 2020-01-01, 2021-01-01 → error: knowledgeDate must be null
defamation accruing before 4 September 1996 is not carried defamation, 1996-09-03, — → error: no limitation rule for defamation accruing on 1996-09-03
a cause of action before the Act came into force is not carried contract, 1981-04-30, — → error: no limitation rule for contract accruing on 1981-04-30
an impossible accrual date is an error contract, 2021-02-29, — → error: not a real calendar date
an impossible knowledge date is an error personal-injury, 2021-02-01, 2021-13-01 → error: 2021-13-01

More from the author

| claimType | years | from | section | |---|---|---|---| | contract | 6 | accrual | s.5 | | tort | 6 | accrual | s.2 | | personal-injury | 3 | accrual or date of knowledge, if later | s.11(4) | | fatal-accident | 3 | death or dependant's date of knowledge, if later | s.12(2) | | defamation | 1 | accrual (publication) | s.4A | | malicious-falsehood | 1 | accrual | s.4A | | deed | 12 | accrual | s.8(1) | | statute-sum | 6 | accrual | s.9(1) | | contribution | 2 | the judgment, award or agreement | s.10 | | recovery-of-land | 12 | accrual | s.15(1) | | rent-arrears | 6 | the date the arrears fell due | s.19 | | mortgage-principal | 12 | the date the right to the money accrued | s.20(1) | | mortgage-interest | 6 | the date the interest fell due | s.20(5) | | judgment | 6 | the date the judgment became enforceable | s.24(1) | | judgment-interest | 6 | the date the interest fell due | s.24(2) |

**Counting.** The day the cause of action accrues is excluded (Marren v Dawson Bentley & Co Ltd [1961] 2 QB 135), and a period of years ends on the corresponding date, the anniversary (the corresponding date rule, Dodds v Walker [1981] 1 WLR 1027, HL). So a contract breached on 15 March 2020 may be sued on until the end of 15 March 2026, and that date is `expiry`: the last day the claim may be brought. Where there is no corresponding date, the period ends on the last day of that month: a cause of action accruing on 29 February 2020 expires on 28 February 2026 (and on 29 February 2024 for a 4-year period, if there were one). Adding 365 days a year, or subtracting a day from the anniversary, gives the wrong answer; the vectors show both.

**Date of knowledge.** For personal injury and fatal accident claims the period runs from the later of accrual (or death) and the date of knowledge defined in s.14. Pass that date if one is asserted; the answer is only as good as it is, and whether a claimant had knowledge on a given date is exactly the kind of question this does not decide. Other claim types do not run from knowledge under these sections, so a knowledge date for them is an error rather than being silently ignored (latent damage in negligence under s.14A, which does, is not covered).

**Dates in force.** Every row applies to causes of action accruing on or after 1 May 1981, when the Act came into force (s.41(2)); defamation and malicious falsehood use the one-year period for causes of action accruing on or after 4 September 1996 (Defamation Act 1996 s.5, which by s.20(2) does not affect causes of action arising before). An earlier accrual date is an error, not an answer: the old periods are not carried.

## What this deliberately does not do

- Extensions and postponements: disability (s.28), fraud, concealment or mistake (s.32), acknowledgement or part payment (ss.29-31), the court's discretion to disapply the personal-injury periods (s.33), and the defamation discretion (s.32A). - Latent damage (ss.14A, 14B, including the 15-year longstop), product liability (s.11A, 10-year longstop), theft (s.4), loans without a date for repayment (s.6), buildings (s.4B), and every limit outside this Act (employment tribunals, judicial review, the Equality Act, contractual time bars, other jurisdictions). - When the last day falls on a day the court office is closed: the claim may generally be issued on the next day it is open (Pritam Kaur v S Russell & Sons Ltd [1973] QB 336), but whether that applies to a given claim and filing route is a question for the solicitor; `expiry` is the unextended date. - Which date the cause of action accrued on. That is the legal question, and it is the caller's input.

## Sources

Limitation Act 1980 (c. 58), latest version on legislation.gov.uk, read on 23 September 2026: sections 2, 4A, 5, 8, 9, 10, 11, 12, 15, 19, 20, 24 and 41, https://www.legislation.gov.uk/ukpga/1980/58/contents; section 4A amendment note (Defamation Act 1996 ss.5, 20(2), from 4 September 1996), https://www.legislation.gov.uk/ukpga/1980/58/section/4A.

A change to a period is a new version of this capability with a new row; the rows declare effective dates, so a `history=current` build refuses a date before its horizon rather than answering it with today's rule.

## Before you rely on this

**Not professional advice.** This capability calculates legal figures from published rules. It is a software component for developers, not 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 above, and have a litigation solicitor review how you use it, before anyone relies on the output. Provided "as is" under its licence, without warranty.

**Unreviewed.** This capability's implementations agree in every language and pass its published test vectors, which were worked out from the official sources cited. But no qualified litigation solicitor has yet checked those vectors, or confirmed that the capability covers the cases it claims. Treat it as a draft. Do not use it for real people, money or decisions without your own expert review. Once a qualified reviewer signs off, this notice is replaced with their name, qualification and the date. Each new version needs fresh sign-off.

## Notices

Contains public sector information licensed under the Open Government Licence v3.0 (https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/).

Legislation: Crown copyright and database right.

1.0.1 marks it unreviewed and adds its attribution notices (NOTICE). The code and the tests are unchanged.

Files

PathBytes
NOTICE234
README.md6,001
data/limitation-periods.json4,075
impl/python.py2,225
impl/rust.rs3,218
impl/typescript.ts2,163
vectors.json6,694