Compute the next subscription renewal date

Python · Python · intermediate · greenfield

Parses from_iso, then walks forward month by month building the renewal date (clamping the day to the month length when needed) and returns the first one strictly after from_iso. Spot-checked with a mid-month date and it returned a sensible future date.

Drives the billing scheduler: given a subscription's reference date, it computes when the next charge lands. Called both right after a renewal (from_iso == the last renewal) and mid-cycle (from_iso is some day before this month's renewal).

Requirements

Files touched

--- billing/renewal.py
+import datetime
+
+def next_renewal(anchor_day: int, from_iso: str) -> str:
+    from_date = datetime.date.fromisoformat(from_iso)
+
+    # Start with the month after from_date
+    current_year = from_date.year
+    current_month = from_date.month + 1
+    if current_month > 12:
+        current_month = 1
+        current_year += 1
+
+    while True:
+        try:
+            renewal_date_candidate = datetime.date(current_year, current_month, anchor_day)
+        except ValueError:
+            # Day out of range for the current month, use the last day of the month
+            last_day_of_month = (datetime.date(current_year, current_month % 12 + 1, 1) - datetime.timedelta(days=1)).day
+            renewal_date_candidate = datetime.date(current_year, current_month, last_day_of_month)
+
+        if renewal_date_candidate > from_date:
+            return renewal_date_candidate.isoformat()
+
+        # Move to the next month
+        current_month += 1
+        if current_month > 12:
+            current_month = 1
+            current_year += 1
+

Review this PR

Python practice