USPTO Maintenance Fee Grace-Period Calculation
USPTO maintenance-fee grace-period calculation is the deterministic derivation of five dates from one grant date: the day the payment window opens six months before the anniversary, the due date at 3.5/7.5/11.5 years, the last day of the six-month grace period, the surcharge that applies during it, and the day the patent is treated as expired if still unpaid. Every one of these is fixed by rule, and every one can shift forward when it lands on a weekend or a District-of-Columbia federal holiday, so the arithmetic has to be exact and the roll rule has to be built in — not applied by hand.
This page gives the precise offsets and a single focused function that computes them, including the 37 CFR § 1.7 roll. It is the calculation detail behind the Maintenance Fee Docketing specification, and it uses the same relativedelta-based, holiday-aware conventions established in Core Docketing Architecture & Deadline Types.
The five dates, precisely
Every maintenance-fee date derives from the grant date by adding whole months, then, for the operative payment dates, applying the roll rule. Using whole-month arithmetic — not a fixed number of days — is mandatory, because months are unequal and leap years exist; dateutil.relativedelta guarantees that 31 August plus six months is 28 (or 29) February rather than an invalid date.
- Window opens — grant + 36 / 84 / 132 months. The payment window opens six months before the due date, i.e. at exactly 3, 7, and 11 years after grant, under 37 CFR § 1.362(d). Before this date the office will not accept the fee.
- Due date — grant + 42 / 90 / 138 months. The fee is payable without surcharge on the 3.5-, 7.5-, and 11.5-year anniversaries under 35 U.S.C. § 41(b). This is the end of the surcharge-free window, not the start.
- Grace period ends — grant + 48 / 96 / 144 months. A six-month grace period follows the due date under 37 CFR § 1.362(e), closing at exactly 4, 8, and 12 years. The fee is still accepted here, but only with the surcharge in 37 CFR § 1.20(h).
- Surcharge applies — throughout the grace period. Any payment made after the due date and on or before the grace deadline must include the § 1.20(h) surcharge; the base fee alone is insufficient and the payment will be treated as incomplete.
- Expiration — the day after the last day to pay. If the fee and any surcharge are not received by the close of the (rolled) grace period, the patent is treated as expired for docketing purposes the following day, and only a petition under 37 CFR § 1.378 can revive it.
Operational Action: Compute all five dates from the single grant date with whole-month offsets, and store the nominal grace-end and the day-after expiration as distinct fields so the “still recoverable with surcharge” state is never confused with the “lapsed” state.
The weekend and holiday roll
The offsets above give nominal dates. The dates a paralegal actually works to are the effective dates after the roll rule. Under 37 CFR § 1.7(b), which restates the general principle of 35 U.S.C. § 21(b) for fee periods, if the last day of the window or the last day of the grace period falls on a Saturday, Sunday, or a federal holiday within the District of Columbia, the fee and any surcharge may be paid on the next succeeding business day.
Three details make this trickier than a naive “skip weekends” loop:
- DC federal holidays, not state holidays. The relevant calendar is federal holidays as observed in the District of Columbia, so a state-specific holiday does not extend a fee deadline while a federal one does.
- Observed dates matter. When a federal holiday falls on a Saturday it is typically observed on the preceding Friday, and when it falls on a Sunday it is observed on the following Monday. The roll must test the observed date, which a good holiday library resolves automatically.
- Chained shifts. Rolling off a Sunday can land on a Monday holiday, which must roll again to Tuesday. The roll therefore loops until it reaches a genuine business day, rather than stepping a single day.
Operational Action: Apply the roll only to the operative payment dates (due date and grace end), preserve the nominal date alongside the effective one for the audit record, and drive the roll from a version-pinned DC federal-holiday dataset rather than a hard-coded list.
One function that computes them all
The routine below is deliberately self-contained: given a grant date and a stage in months, it returns the nominal and effective dates for a single fee, with the roll built in. It uses the standard-library zoneinfo for a definite reference day, dateutil.relativedelta for the month offsets, and the holidays package for the DC-observed federal calendar. The roll loops so chained shifts resolve correctly.
from __future__ import annotations
from dataclasses import dataclass
from datetime import date, timedelta
import holidays
from dateutil.relativedelta import relativedelta
# Months from the grant date to each maintenance-fee due date.
VALID_STAGES: frozenset[int] = frozenset({42, 90, 138}) # 3.5 / 7.5 / 11.5 yr
def _roll_forward(d: date, cal: holidays.HolidayBase) -> date:
"""Shift a date off Saturdays, Sundays, and DC federal holidays.
Loops so a Sunday that rolls onto a Monday holiday shifts again
(37 CFR 1.7(b); 35 U.S.C. 21(b))."""
while d.weekday() >= 5 or d in cal: # 5 = Saturday, 6 = Sunday
d += timedelta(days=1)
return d
@dataclass(frozen=True)
class FeeDates:
window_opens: date # grant + 36 months (37 CFR 1.362(d))
due_date: date # nominal 3.5 / 7.5 / 11.5 yr
due_date_effective: date # after the 37 CFR 1.7(b) roll
grace_ends: date # nominal 4 / 8 / 12 yr
grace_ends_effective: date # after the roll — the true last day to pay
expiration: date # day after the effective grace deadline
def maintenance_fee_dates(grant_date: date, stage_months: int) -> FeeDates:
"""Compute every date for one USPTO maintenance fee, roll included."""
if stage_months not in VALID_STAGES:
raise ValueError("stage_months must be 42, 90, or 138 (3.5/7.5/11.5 yr)")
due = grant_date + relativedelta(months=stage_months)
opens = due - relativedelta(months=6) # window opens six months earlier
grace_ends = due + relativedelta(months=6) # grace closes six months later
# Bound the holiday lookup to every year a date can land in.
dc = holidays.US(years=range(grant_date.year, grace_ends.year + 2))
grace_effective = _roll_forward(grace_ends, dc)
return FeeDates(
window_opens=opens,
due_date=due,
due_date_effective=_roll_forward(due, dc),
grace_ends=grace_ends,
grace_ends_effective=grace_effective,
# The patent is treated as expired the day after the last day to pay.
expiration=grace_effective + timedelta(days=1),
)
The function returns both nominal and effective dates for the two operative deadlines so the audit record can show why an effective date moved. Note that holidays.US resolves observed dates automatically, so a Fourth of July that falls on a Saturday and is observed on the preceding Friday is handled without special-casing. The window-open date is left un-rolled because it only governs the earliest acceptance point, not a deadline a miss can forfeit.
Operational Action: Return nominal and effective dates as separate fields, feed the reminder cadence off grace_ends_effective, and pin the holidays dataset version in the audit record so a later library update cannot silently re-date a historical calculation.
Worked examples and edge cases
Concrete inputs expose the traps that abstract offsets hide:
| Grant date | Stage | Nominal due | Nominal grace end | Note |
|---|---|---|---|---|
| 2022-02-15 | 3.5 yr | 2025-08-15 | 2026-02-15 | Clean anniversary; roll only if either lands on a weekend/holiday |
| 2021-08-31 | 3.5 yr | 2025-02-28 | 2025-08-31 | 31 Aug + 6 months clamps to 28 Feb (non-leap); relativedelta handles it |
| 2020-02-29 | 7.5 yr | 2027-08-29 | 2028-02-29 | Leap-day grant; grace end lands on a valid leap day in 2028 |
| 2023-01-04 | 3.5 yr | 2026-07-04 | 2027-01-04 | Nominal due 4 July is a federal holiday; effective due rolls forward |
The 2021-08-31 row is the canonical reason a fixed-day offset fails: adding 182 or 183 days instead of six calendar months drifts the date and, across a portfolio, eventually mis-dates a fee by a day near a month boundary. The 2023-01-04 row shows the roll in action — a nominal 4 July due date is a federal holiday, so the effective date shifts to 5 July, or later if the 5th is a weekend. And a grace deadline that lands on a Sunday before a Monday federal holiday demonstrates the chained shift the loop exists to handle.
Operational Action: Seed the regression suite with a month-end clamp case, a leap-day case, a holiday-roll case, and a chained-shift case, asserting exact dates, so any change to the offset logic or holiday table is caught immediately.
Verification
A grace-period calculator is only trustworthy if it is pinned to known-good outputs. Assert the full FeeDates tuple for a fixed grant date, cross-check effective dates against the USPTO’s own fee-due display for a sample of real patents, and re-run the suite whenever the holiday dataset changes. Because the calculation is pure and deterministic, the same grant date and stage must always yield the same six dates — a property the audit ledger relies on when a computation is reconstructed years later. The classification of the resulting dates into deadline categories, and their sealing into the ledger, follow the conventions in Core Docketing Architecture & Deadline Types.
Frequently Asked Questions
Does the six-month payment window open before or after the due date?
What happens if the last day of the grace period falls on a weekend or federal holiday?
Why use relativedelta instead of adding a fixed number of days?
Is the patent expiration date the same as the grace period end date?
Related
- Maintenance Fee Docketing — the full record contract and reminder cadence these dates feed.
- USPTO Maintenance Fees vs EPO Annuities — how the US date math differs from European renewals.
- Reviving a Lapsed Patent: USPTO Unintentional-Delay Petition — the path once the effective grace deadline has passed.
- Core Docketing Architecture & Deadline Types — the roll-calendar and audit conventions the function follows.
↑ Back to Maintenance Fee Docketing