UK Bank Holiday & BACS Working Day Calendar
UK Bank Holiday & BACS Working Day Calendar
The Direct Debit service includes a built-in UK bank holiday calendar and a BACS working day utility. Together these ensure that all collection dates, receipt dates, and mandate schedules are accurate and compliant with the BACS processing cycle.
Why This Matters
BACS Direct Debit operates on UK banking working days only — weekends and bank holidays are not processing days. Getting this wrong leads to:
- Collections submitted on non-processing days being rejected or delayed.
- Tenants seeing incorrect "funds leave your account" or "funds received" dates on the mandate form.
- Month-end mandates silently shifting to the wrong calendar date.
This utility is the single source of truth for all date arithmetic in the service.
Bank Holiday Data
A bank_holidays table is seeded from the official UK Government bank holidays API and kept current automatically. Only the England & Wales division is used, as this is the jurisdiction applicable to BACS Direct Debit processing.
Working Day Utility
All date calculations are performed server-side via a dedicated utility module. The following functions are available internally and underpin all scheduling, mandate form date display, and collection submission logic.
isBACSWorkingDay(date)
Returns true if the supplied date is a valid BACS working day.
A date is a BACS working day if it is:
- A Monday through Friday, and
- Not a UK bank holiday (England & Wales).
isBACSWorkingDay('2025-12-25') // false — Christmas Day
isBACSWorkingDay('2025-12-26') // false — Boxing Day
isBACSWorkingDay('2025-12-29') // true
addWorkingDays(date, n)
Returns the date that is n BACS working days after the supplied date, skipping weekends and bank holidays.
addWorkingDays('2025-04-17', 3) // skips Good Friday, Easter Monday
subtractWorkingDays(date, n)
Returns the date that is n BACS working days before the supplied date, skipping weekends and bank holidays in reverse.
collectionDateToReceiptDate(collectionDate)
Resolves a collection date to its expected receipt date. The default offset is T+3 BACS working days, reflecting the standard BACS credit clearing cycle.
This is used on the mandate form to show tenants two distinct dates:
| Label | Meaning |
|---|---|
| Collection date | When funds leave the tenant's bank account |
| Receipt date | When the agent expects to receive the funds |
collectionDateToReceiptDate('2025-06-02') // '2025-06-05' (T+3 working days)
Edge Case Handling
February 29 / 30 / 31
Monthly mandates can be set to collect on a specific day of the month (e.g. the 31st). When the scheduled day does not exist in a given month (most commonly February, but also shorter months for the 29th–31st), the date is rolled forward to the 1st of the following month before BACS working day resolution is applied.
| Scheduled day | Month | Resolved calendar date |
|---|---|---|
| 29 | February (non-leap) | 1 March |
| 30 | February (non-leap) | 1 March |
| 31 | February | 1 March |
| 31 | April | 1 May |
Sunday-to-Monday Adjustment
If a resolved collection date falls on a Sunday, it is advanced to the following Monday before BACS working day checks are applied. This ensures the date is never a non-processing day prior to further working day calculations.
Relationship to Other Features
- Mandate Form — The payment details step uses
collectionDateToReceiptDateto display the collection date and receipt date pair to the tenant before they confirm. - Collection Scheduling — The collection submission job uses
isBACSWorkingDayandaddWorkingDaysto determine valid submission windows. - Alert Thresholds — Upcoming collection forecasting relies on the working day calendar to project amounts due within a given period.