education.school-year-group@1.0.0
impl/typescript.ts
1,633 bytes · the TypeScript implementation · view 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 { COHORT_RULES, YEAR_GROUPS } from "./education_school_year_group_data.ts"; ← this capability’s own data, compiled from data/cohort-rules.json into the same file by fune build
import { type SchoolYearGroup, type UkNation } from "./education_school_year_group_types.ts";
/**
* The year group a child is in on a date, placed by their birth date.
*
* The cohort comes from the birth date itself (born on or after the cohort
* start joins a year later), never from an age on a cut-off date, which
* misplaces 29 February births where the cohort starts on 1 March.
*/
export function schoolYearGroup(birthDate: string, onDate: string, nation: UkNation): SchoolYearGroup {
const birth = parseIsoDate(birthDate);
const on = parseIsoDate(onDate);
if (onDate < birthDate) {
throw new RangeError(`onDate ${onDate} is before birthDate ${birthDate}`);
}
const rule = COHORT_RULES.find((r) => r.nation === nation);
if (rule === undefined) {
throw new RangeError(`unknown nation "${nation}": use england, wales, scotland or northern-ireland`);
}
const birthMonthDay = birthDate.slice(5);
const onMonthDay = onDate.slice(5);
const entryYear = birth.year + rule.entryAge + (birthMonthDay >= rule.cohortStart ? 1 : 0);
const startYear = onMonthDay >= rule.schoolYearStart ? on.year : on.year - 1;
const index = startYear - entryYear;
const name = YEAR_GROUPS.find((g) => g.nation === nation && g.index === index);
return {
schoolYearStart: `${String(startYear).padStart(4, "0")}-${rule.schoolYearStart}`,
entryYear,
index,
yearGroup: name === undefined ? null : name.label,
stage: name === undefined ? null : name.stage,
};
}