From bf1ec322ceb7790ee2d62dba0a63e63e18da13a1 Mon Sep 17 00:00:00 2001 From: Bernard Siebens Date: Mon, 27 Jul 2026 10:22:42 +0200 Subject: [PATCH] Simplify add_one_year using dateutil.relativedelta Replaces the hand-rolled leap-day fallback with the library that already handles it, and already sits in the dependency tree. --- billing/models.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/billing/models.py b/billing/models.py index 56fc53f..884b9d7 100644 --- a/billing/models.py +++ b/billing/models.py @@ -9,6 +9,7 @@ by one, and a tenant-scoped manager would be exactly the wrong default. from datetime import date, timedelta from decimal import Decimal +from dateutil import relativedelta from django.conf import settings from django.core.validators import MinValueValidator from django.db import models @@ -19,22 +20,17 @@ from rosterchief.base import UUIDModel, unique_slugify ZERO = Decimal("0.00") -#: A club stays live for six weeks past the end of an unpaid period before it is archived. +# A club stays live for six weeks past the end of an unpaid period before it is archived. GRACE_DAYS = 45 -#: The next period is issued this long before the current one ends, so the invoice reaches the -#: club — and can be paid — before the old period lapses. Grace then only matters for genuine -#: non-payers, rather than for everyone who takes a fortnight to pay a bank transfer. +# The next period is issued this long before the current one ends, so the invoice reaches the +# club — and can be paid — before the old period lapses. Grace then only matters for genuine +# non-payers, rather than for everyone who takes a fortnight to pay a bank transfer. RENEWAL_LEAD_DAYS = 30 def add_one_year(day: date) -> date: - """The day one year on. 29 February has no counterpart in a common year, so it falls - back to the 28th rather than raising.""" - try: - return day.replace(year=day.year + 1) - except ValueError: - return day.replace(year=day.year + 1, day=28) + return day + relativedelta.relativedelta(years=1) class Tier(UUIDModel):