Spanish tax calendar
When each Spanish tax form falls due, computed rather than copied from a table.
Open-source libraries · Python · Code published
The problem
A filing deadline looks like a fact and is a calculation. The day depends on the form, it shifts if it lands on a Saturday, Sunday or public holiday, and it moves five days earlier when payment is direct-debited. Any hand-written calendar is correct the year it is written and silently wrong the next.
What it does
- Computes the deadline for the quarterly, annual and campaign forms of the Spanish tax agency.
- Shifts the due date when it falls on a non-working day, per article 30.5 of Act 39/2015.
- Brings the deadline five days forward when the filing is paid by direct debit.
- Locates Good Friday with the Meeus/Jones/Butcher algorithm instead of listing years by hand.
What was decided while building it
- Easter is computed, not listed
- Good Friday is the only movable national holiday, and the temptation is to write ten years into a table. That table expires without warning: year eleven returns a wrong date and nothing looks odd. With the Meeus/Jones/Butcher algorithm, year eleven comes out as well as the first.
- The shift comes from the law that states it
- A deadline landing on a non-working day moving to the next working day is not a custom: it is article 30.5 of Act 39/2015, cited in the code right beside the line that applies it. A rule without its source next to it is a rule nobody can review without researching it again from scratch.
- Direct debit shortens the deadline, it does not extend it
- Direct-debiting the payment moves the real filing date five days earlier, and it is the most expensive mistake of the set because it runs against intuition: anyone assuming direct debit buys time files late. It is an explicit parameter, not a special case buried somewhere.
How far it goes
- It fills in no form, computes no amount and files nothing with the tax agency.
- It is not tax advice: it says when a form falls due, not whether you are required to file it.
- Coverage is the list of forms declared in the repository. A form outside that list has no date.
- Form 100 only returns a date for the campaign years verified in the repository.
- 0 dependencies
- MIT licence
- 3.9+ Python
Built with
- Python
- datetime