banking.bacs-processing-date@1.0.0
impl/typescript.ts
1,977 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 { addBusinessDays } from "./dates_add_business_days.ts"; ← from dates.add-business-days ^1.0.0 · built alongside by fune
import { bankHolidays } from "./dates_bank_holidays.ts"; ← from dates.bank-holidays ^1.0.0 · built alongside by fune
import { isWeekday } from "./dates_day_of_week.ts"; ← from dates.day-of-week ^1.0.0 · built alongside by fune
import { type BacsCycle } from "./banking_bacs_processing_date_types.ts";
function holidaysFor(years: readonly number[]): string[] {
const out: string[] = [];
for (const year of years) {
for (const holiday of bankHolidays("england-and-wales", year)) out.push(holiday.date);
}
return out;
}
function cycleWith(submissionIso: string, afterCutoff: boolean, holidays: readonly string[]): BacsCycle {
const processingDay = isWeekday(submissionIso) && !holidays.includes(submissionIso);
const inputDay = processingDay && !afterCutoff ? submissionIso : addBusinessDays(submissionIso, 1, holidays);
return {
inputDay,
processingDay: addBusinessDays(inputDay, 1, holidays),
entryDay: addBusinessDays(inputDay, 2, holidays),
};
}
/**
* The Bacs cycle a file joins. Bacs works on processing days - Monday to
* Friday except England and Wales bank holidays - and a file joins the cycle
* whose input day is the day it arrives, if that is a processing day and it
* arrived before the 22:30 deadline, or the next processing day otherwise.
* Processing is the next processing day and entry the one after.
*/
export function bacsProcessingDates(submissionIso: string, afterCutoff: boolean): BacsCycle {
// isWeekday validates the date before its year is read.
isWeekday(submissionIso);
const year = Number(submissionIso.slice(0, 4));
// Only reach for next year's calendar when the cycle really runs into it,
// so a December submission in the last published year still works as long
// as its cycle ends inside that year.
let cycle = cycleWith(submissionIso, afterCutoff, holidaysFor([year]));
if (cycle.entryDay.slice(0, 4) !== submissionIso.slice(0, 4)) {
cycle = cycleWith(submissionIso, afterCutoff, holidaysFor([year, year + 1]));
}
return cycle;
}