use super::funejson::Value; use super::dates_add_days::parse_iso_date; use super::education_school_year_group_data::{COHORT_RULES, YEAR_GROUPS}; /// 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. /// /// # Panics /// Panics on a malformed date, onDate before birthDate, or an unknown nation. pub fn school_year_group(birth_date: &str, on_date: &str, nation: &str) -> SchoolYearGroup { let birth = parse_iso_date(birth_date); let on = parse_iso_date(on_date); if on_date < birth_date { panic!("onDate {} is before birthDate {}", on_date, birth_date); } let rule = match COHORT_RULES.iter().find(|r| r.nation == nation) { Some(r) => r, None => panic!("unknown nation \"{}\": use england, wales, scotland or northern-ireland", nation), }; let entry_year = birth.year + rule.entry_age + if &birth_date[5..] >= rule.cohort_start { 1 } else { 0 }; let start_year = if &on_date[5..] >= rule.school_year_start { on.year } else { on.year - 1 }; let index = start_year - entry_year; let name = YEAR_GROUPS.iter().find(|g| g.nation == nation && g.index == index); SchoolYearGroup { school_year_start: format!("{:04}-{}", start_year, rule.school_year_start), entry_year, index, year_group: name.map(|g| g.label.to_string()), stage: name.map(|g| g.stage.to_string()), } } pub fn school_year_group_to_value(g: &SchoolYearGroup) -> Value { let opt = |v: &Option| match v { Some(s) => Value::str(s), None => Value::Null, }; Value::obj(vec![ ("schoolYearStart", Value::str(&g.school_year_start)), ("entryYear", Value::Int(g.entry_year)), ("index", Value::Int(g.index)), ("yearGroup", opt(&g.year_group)), ("stage", opt(&g.stage)), ]) } pub fn fune_vector(args: &[Value]) -> Value { school_year_group_to_value(&school_year_group(args[0].as_str(), args[1].as_str(), args[2].as_str())) }