banking.bacs-processing-date@1.0.0
impl/python.py
2,100 bytes · the Python 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.
from typing import List, Sequence
from .banking_bacs_processing_date_types import BacsCycle
from .dates_add_business_days import add_business_days ← from dates.add-business-days ^1.0.0 · built alongside by fune
from .dates_bank_holidays import bank_holidays ← from dates.bank-holidays ^1.0.0 · built alongside by fune
from .dates_day_of_week import is_weekday ← from dates.day-of-week ^1.0.0 · built alongside by fune
def _holidays_for(years: Sequence[int]) -> List[str]:
out: List[str] = []
for year in years:
out.extend(holiday.date for holiday in bank_holidays("england-and-wales", year))
return out
def _cycle_with(submission_iso: str, after_cutoff: bool, holidays: Sequence[str]) -> BacsCycle:
processing_day = is_weekday(submission_iso) and submission_iso not in holidays
input_day = submission_iso if processing_day and not after_cutoff else add_business_days(submission_iso, 1, holidays)
return BacsCycle(
input_day=input_day,
processing_day=add_business_days(input_day, 1, holidays),
entry_day=add_business_days(input_day, 2, holidays),
)
def bacs_processing_dates(submission_iso: str, after_cutoff: bool) -> BacsCycle:
"""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.
"""
if not isinstance(after_cutoff, bool):
raise TypeError("afterCutoff must be a boolean, received %r" % (after_cutoff,))
# is_weekday validates the date before its year is read.
is_weekday(submission_iso)
year = int(submission_iso[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.
cycle = _cycle_with(submission_iso, after_cutoff, _holidays_for([year]))
if cycle.entry_day[0:4] != submission_iso[0:4]:
cycle = _cycle_with(submission_iso, after_cutoff, _holidays_for([year, year + 1]))
return cycle